题目描述 Description
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值 = min{|该天以前某一天的营业额-该天营业额|}
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。
输入描述 Input Description
第一行为正整数n(n<=32767),表示该公司从成立一直到现在的天数,接下来的n行每行有一个正整数ai(ai<=1000000),表示第i天公司的营业额。
输出描述 Output Description
输出文件仅有一个正整数,即每天最小波动值之和,小于231
样例输入 Sample Input
6
5
1
2
5
4
6
样例输出 Sample Output
12
数据范围及提示 Data Size & Hint
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
思路:
裸treap模板;
支持插入,寻找前驱、后继操作;
每次插入一个点
然后寻找这个点的前驱和后继,比较哪个的波动小然后累加
来,上代码:
#include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; struct TreeNode { int key,fix,weight,size; TreeNode *left,*right; }; class TreapType { private: TreeNode *null,*root,*start; int n,if_z,pos,ans; char Cget; inline void read_int(int &now) { now=0,if_z=1,Cget=getchar(); while(Cget>'9'||Cget<'0') { if(Cget=='-') if_z=-1; Cget=getchar(); } while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } now*=if_z; } public: TreapType() { null=new TreeNode; null->left=null; null->right=null; root=null; start=new TreeNode; start->key=0x7ffffff; start->left=null; start->right=null; read_int(n); read_int(pos); ans+=abs(pos); Insert(root,pos); for(int i=2;i<=n;i++) { read_int(pos); Insert(root,pos); int pre=Predecessor(root,pos,start); int suc=Successor(root,pos,start); ans+=min(abs(pre-pos),abs(suc-pos)); } printf("%d ",ans); } void Rotato_Left(TreeNode *&now) { TreeNode *tmp=now->right; now->right=tmp->left; tmp->left=now; now=tmp; now->left->size=now->left->left->size+now->left->weight+now->left->right->size; now->size=now->left->size+now->right->size+now->weight; } void Rotato_Right(TreeNode *&now) { TreeNode *tmp=now->left; now->left=tmp->right; tmp->right=now; now=tmp; now->right->size=now->right->left->size+now->right->weight+now->right->left->size; now->size=now->left->size+now->weight+now->right->size; } void Insert(TreeNode *&now,int key) { if(now==null) { now=new TreeNode; now->fix=rand(); now->key=key; now->left=null; now->right=null; now->size=1; now->weight=1; return ; } if(now->key==key) { now->weight++; } else if(now->key<key) { Insert(now->right,key); if(now->right->fix>now->fix) Rotato_Left(now); } else if(now->key>key) { Insert(now->left,key); if(now->left->fix>now->fix) Rotato_Right(now); } now->size=now->left->size+now->right->size+now->weight; } int Predecessor(TreeNode *&now,int key,TreeNode *&optimal) { if(now==null) return optimal->key; if(now->key==key) { if(now->weight>1) return key; else return Predecessor(now->left,key,optimal); } else { if(now->key<key) return Predecessor(now->right,key,now); else return Predecessor(now->left,key,optimal); } } int Successor(TreeNode *&now,int key,TreeNode *&optimal) { if(now==null) return optimal->key; if(now->key==key) { if(now->weight>1) return key; else return Successor(now->right,key,optimal); } else { if(now->key>key) return Successor(now->left,key,now); else return Successor(now->right,key,optimal); } } }; class TreapType do_; int main() { return 0; }