LOJ10043

题目描述

原题来自:HNOI 2002

Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。

经济管理学上定义了一种最小波动值来衡量这种情况:记该天以前某一天的营业额为ai,该天营业额为 b,则该天的最小波动值min | ai-b | ,当最小波动值越大时,就说明营业情况越不稳定。而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。

你的任务就是编写一个程序帮助 Tiger 来计算这一个值,第一天的最小波动值为第一天的营业额。

一句话题意

给出一个n个数的数列{an},对于第 i 个元素ai ,定义fi =min | ai - ai|,其中1<=j<=i,fi=a1 。求 Σfi

输入格式

第一行为正整数,表示该公司从成立一直到现在的天数;

接下来的n行每行有一个正整数,表示第 i 天公司的营业额ai 

输出格式

仅有一个正整数,即每一天最小波动的和,结果不超过1<<31 

样例

样例输入

6
5
1
2
5
4
6

样例输出

12

样例说明

数据范围与提示

对于全部数据,1<=n<=215 ,ai<=106

_________________________________

平衡树中查找前驱后继,然后和当前值取差,取较小的加入最终结果。

继续熟悉FHQ_TREAP

_________________________________

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=(1<<15)+10;
 4 const int inf=1e7;
 5 int n;
 6 struct node
 7 {
 8     int lc,rc,val,rd,siz;
 9 }tr[maxn];
10 int cnt,root;
11 long long ans;
12 int newnode(int v)
13 {
14     ++cnt;
15     tr[cnt].lc=tr[cnt].rc=0;
16     tr[cnt].val=v;
17     tr[cnt].rd=rand();
18     tr[cnt].siz=1;
19     return cnt;
20 }
21 void update(int x)
22 {
23     tr[x].siz=tr[tr[x].lc].siz+tr[tr[x].rc].siz+1;
24 }
25 int merge(int x,int y)
26 {
27     if(x*y==0)return x+y;
28     if(tr[x].rd<tr[y].rd)
29     {
30         tr[x].rc=merge(tr[x].rc,y);
31         update(x);
32         return x;
33     }
34     else
35     {
36         tr[y].lc=merge(x,tr[y].lc);
37         update(y);
38         return y;
39     }
40 }
41 void split(int cur,int k,int &x,int &y)
42 {
43     if(!cur)x=y=0;
44     else
45     {
46         if(tr[cur].val<=k)
47         {
48             x=cur;
49             split(tr[cur].rc,k,tr[cur].rc,y);
50         }
51         else 
52         {
53             y=cur;
54             split(tr[cur].lc,k,x,tr[cur].lc);
55         }
56         update(cur);
57     }
58 }
59 int kth(int now,int v)
60 {
61     int cur=now;
62     while(cur)
63     {
64         if(tr[tr[cur].lc].siz+1==v)return tr[cur].val;
65         else if(tr[tr[cur].lc].siz>=v)cur=tr[cur].lc;
66         else v-=tr[tr[cur].lc].siz+1,cur=tr[cur].rc;
67     }
68     return inf;
69 }
70 void work(int v)
71 {
72     int x,y,tp=inf,tpp;
73     split(root,v,x,y);
74     tpp=kth(x,tr[x].siz);
75     tp=tpp==inf?inf:v-tpp;
76     tpp=kth(y,1);
77     tp=tpp==inf?tp:min(tp,tpp-v);
78     if(tp!=inf)ans+=tp;
79     root=merge(merge(x,newnode(v)),y);
80 }
81 int main()
82 {
83     scanf("%d",&n);
84     for(int x,i=0;i<n;++i)
85     {
86         scanf("%d",&x);
87         if(i==0)ans=x;
88         work(x);
89     }
90     cout<<ans;
91     return 0;
92 }
View Code
原文地址:https://www.cnblogs.com/gryzy/p/10627744.html