1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 12173 Solved: 4354
[Submit][Status][Discuss]
Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
6
5
1
2
5
4
6
5
1
2
5
4
6
Sample Output
12
HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
此题数据有问题,详见讨论版http://www.lydsy.com/JudgeOnline/wttl/wttl.php?pid=1588
此题题面很简单,就是求序列的每一个数与其前面的数中最小的差值。用线段树是可做的,我这里用了Splaytree。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 const int maxn=1e6; 8 int key[maxn],ch[maxn][2],fa[maxn],root,cnt; 9 10 void Rotate(int x) 11 { 12 int y=fa[x],g=fa[y],c=ch[y][1]==x; 13 ch[y][c]=ch[x][c^1];ch[x][c^1]=y; 14 fa[ch[y][c]]=y;fa[y]=x;fa[x]=g; 15 if(g) 16 ch[g][ch[g][1]==y]=x; 17 } 18 19 void Splay(int x) 20 { 21 for(int y;y=fa[x];Rotate(x)) 22 if(fa[y]) 23 Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x); 24 root=x; 25 } 26 27 void Insert(int x) 28 { 29 if(!root){ 30 root=++cnt; 31 key[cnt]=x; 32 return; 33 } 34 int p=root,pre; 35 while(p) 36 { 37 pre=p; 38 p=ch[p][key[p]<x]; 39 } 40 p=++cnt;fa[p]=pre; 41 ch[pre][key[pre]<x]=p; 42 key[p]=x; 43 Splay(p); 44 } 45 int Ql(int x) 46 { 47 int p=root,ret=-1000000000; 48 while(p){ 49 if(key[p]<=x){ 50 ret=max(ret,key[p]); 51 p=ch[p][1]; 52 } 53 else p=ch[p][0]; 54 } 55 return ret; 56 } 57 int Qr(int x) 58 { 59 int p=root,ret=1000000000; 60 while(p){ 61 if(key[p]>=x){ 62 ret=min(ret,key[p]); 63 p=ch[p][0]; 64 } 65 else p=ch[p][1]; 66 } 67 return ret; 68 } 69 int main() 70 { 71 int n,ans=0; 72 scanf("%d",&n); 73 for(int i=1;i<=n;i++) 74 { 75 int x=0; 76 scanf("%d",&x); 77 if(i==1){ 78 ans=x; 79 Insert(x); 80 continue; 81 } 82 int l=Ql(x); 83 int r=Qr(x); 84 ans+=min(x-l,r-x); 85 Insert(x); 86 } 87 printf("%d ",ans); 88 return 0; 89 }
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 using namespace std; 7 const int maxn=50010; 8 int n,a[maxn],p[maxn],rp[maxn],l[maxn],r[maxn]; 9 bool cmp(int x,int y){ 10 return a[x]<a[y]; 11 } 12 int main(){ 13 #ifndef ONLINE_JUDGE 14 freopen("turnover.in","r",stdin); 15 freopen("turnover.out","w",stdout); 16 #endif 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++){ 19 scanf("%d",&a[i]); 20 p[i]=i; 21 } 22 int ans=a[1]; 23 sort(p+1,p+n+1,cmp); 24 for(int i=1;i<=n;i++){ 25 l[i]=i-1;r[i]=i+1; 26 rp[p[i]]=i; 27 } 28 l[1]=n;r[n]=1; 29 for(int i=n;i>=2;i--){ 30 ans+=min(abs(a[i]-a[p[l[rp[i]]]]),abs(a[p[r[rp[i]]]]-a[i])); 31 r[l[rp[i]]]=r[rp[i]]; 32 l[r[rp[i]]]=l[rp[i]]; 33 } 34 printf("%d ",ans); 35 return 0; 36 }