★★ 输入文件:turnover.in
输出文件:turnover.out
简单对比
时间限制:5 s 内存限制:162 MB
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。
6
5
1
2
5
4
6
12
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
HNOI 2002
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=100010; 4 int root,tot,N,ANS; 5 int key[maxn],siz[maxn],lc[maxn],rc[maxn]; 6 void r_rotate(int &rt){ 7 int k=lc[rt]; 8 lc[rt]=rc[k]; 9 rc[k]=rt; 10 siz[k]=siz[rt]; 11 siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1; 12 rt=k; 13 } 14 void l_rotate(int &rt){ 15 int k=rc[rt]; 16 rc[rt]=lc[k]; 17 lc[k]=rt; 18 siz[k]=siz[rt]; 19 siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1; 20 rt=k; 21 } 22 void MAINTAIN(int &rt,bool flag){ 23 if(flag==false){//rt的左子树的某子树>rt的右子树 24 if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);//如果rt的左孩子的左孩子>rt的右孩子,rt右旋 25 else if(siz[rc[lc[rt]]]>siz[rc[rt]]){//如果rt的左孩子L的右孩子B > rt的右孩子R: 26 l_rotate(lc[rt]);//先让rt的左孩子左旋,使rt的左子树变成以B为根 27 r_rotate(rt);//再右旋再变成以B为根 28 } 29 else return;//平衡 30 } 31 else{//rt的右子树的某子树>rt的左子树 32 if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt); 33 else if(siz[lc[rc[rt]]]>siz[lc[rt]]){ 34 r_rotate(rc[rt]); 35 l_rotate(rt); 36 } 37 else return; 38 } 39 MAINTAIN(lc[rt],0); MAINTAIN(rc[rt],1);//检查是否满足平衡 40 MAINTAIN(rt,1); MAINTAIN(rt,0); 41 } 42 void insert(int &rt,int v){ 43 if(rt==0){//找到合适的位置插入 44 rt=++tot; 45 key[rt]=v; 46 lc[rt]=rc[rt]=0; siz[rt]=1; 47 return ; 48 } 49 siz[rt]++; 50 if(v<=key[rt]) insert(lc[rt],v); 51 else insert(rc[rt],v); 52 MAINTAIN(rt,v>key[rt]);//调整树结构 53 } 54 bool find(int &rt,int v){//查找是否有 key值为 v的节点 55 if(rt==0) return false; 56 else if(v==key[rt]) return true; 57 else if(v<key[rt]) return find(lc[rt],v); 58 else if(v>key[rt]) return find(rc[rt],v); 59 } 60 int pred(int &rt,int v){//返回比 v小的最大的数 61 if(rt==0) return v;//要求是比v小,返回v的意思是没找到 62 if(v<=key[rt]) return pred(lc[rt],v);//key[rt]>v 必然要往更小的方向,即rt的左子树 63 else{//此时 key[rt]<v,而rt的右子树的key值都大于key[rt] 64 int ans=pred(rc[rt],v); 65 if(ans==v) return key[rt];//返回v表示rt的右子树中的key都比v大,返回key[rt] 66 } 67 } 68 int succ(int &rt,int v){//返回比v大的最小的数 69 if(rt==0) return v; 70 if(v>=key[rt]) return succ(rc[rt],v); 71 else{ 72 int ans=succ(lc[rt],v); 73 if(ans==v) return key[rt]; 74 } 75 } 76 int main(){ 77 scanf("%d",&N); 78 for(int i=1,num;i<=N;i++){ 79 if(scanf("%d",&num)==EOF) num=0; 80 if(find(root,num)==true) continue; 81 if(siz[root]==0){ 82 ANS+=num; insert(root,num); continue; 83 } 84 int tmp1=pred(root,num); int tmp2=succ(root,num); 85 if(find(root,tmp1)==true&&(find(root,tmp2)==false||abs(num-tmp1)<=abs(num-tmp2))){ 86 ANS+=abs(num-tmp1); 87 insert(root,num); 88 } 89 else if(find(root,tmp2)==true&&(find(root,tmp1)==false||abs(num-tmp1)>abs(num-tmp2))){ 90 ANS+=abs(num-tmp2); 91 insert(root,num); 92 } 93 } 94 printf("%d",ANS); 95 return 0; 96 }
原文:http://www.cnblogs.com/CXCXCXC/p/5095138.html