BZOJ1588 营业额统计 (Splay)
营业额统计
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
6 5 1 2 5 4 6
12
此模板里的查前驱后继是正确的。
#include <iostream> #include <cstring> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <time.h> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 102 using namespace std; const int inf=0x3f3f3f3f; const int MAXN=2e5+100; int lim; struct SplayTree { int sz[MAXN]; int ch[MAXN][2]; int pre[MAXN]; int rt,top; inline void up(int x) { sz[x] = cnt[x] + sz[ ch[x][0] ] + sz[ ch[x][1] ]; } inline void Rotate(int x,int f) { int y=pre[x]; ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x; ch[x][f] = y; pre[y] = x; up(y); } inline void Splay(int x,int goal) { //将x旋转到goal的下面 while(pre[x] != goal) { if(pre[pre[x]] == goal) Rotate(x, ch[pre[x]][0] == x); else { int y=pre[x],z=pre[y]; int f = (ch[z][0]==y); if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } up(x); if(goal==0) rt=x; } inline void RTO(int k,int goal) { //将第k位数旋转到goal的下面 int x=rt; while(sz[ ch[x][0] ] != k-1) { if(k < sz[ ch[x][0] ]+1) x=ch[x][0]; else { k-=(sz[ ch[x][0] ]+1); x = ch[x][1]; } } Splay(x,goal); } inline void vist(int x) { if(x) { printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d sz=%d\n",x,ch[x][0],ch[x][1],val[x],sz[x]); vist(ch[x][0]); vist(ch[x][1]); } } inline void Newnode(int &x,int c) { x=++top; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x]=1; cnt[x]=1; val[x] = c; } inline void init() { sum=ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; rt=top=0; cnt[0]=0; Newnode(rt,-inf); Newnode(ch[rt][1],inf); pre[top]=rt; sz[rt]=2; } inline void Insert(int &x,int key,int f) { if(!x) { Newnode(x,key); pre[x]=f; Splay(x,0); return ; } if(key==val[x]) { cnt[x]++; sz[x]++; Splay(x,0); return ; } else if(key<val[x]) { Insert(ch[x][0],key,x); } else { Insert(ch[x][1],key,x); } up(x); } //找前驱 void findpre(int x,int key,int &ans){ if(!x) return ; if(val[x] <= key){ ans=val[x]; findpre(ch[x][1],key,ans); } else findpre(ch[x][0],key,ans); } void findsucc(int x,int key,int &ans){ if(!x) return ; if(val[x]>=key) { ans=val[x]; findsucc(ch[x][0],key,ans); } else findsucc(ch[x][1],key,ans); } void del(int &x,int f) { if(!x) return ; if(val[x]>=lim) { del(ch[x][0],x); } else { sum+=sz[ch[x][0]]+cnt[x]; x=ch[x][1]; pre[x]=f; if(f==0) rt=x; del(x,f); } if(x) up(x); } inline void update() { del(rt,0); } inline int find_kth(int x,int k) { if(k<sz[ch[x][0]]+1) { return find_kth(ch[x][0],k); } else if(k > sz[ ch[x][0] ] + cnt[x] ) return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x]); else { Splay(x,0); return val[x]; } } int cnt[MAXN]; int val[MAXN]; int sum; } spt; int main() { int n; scanf("%d",&n); spt.init(); int ans=0,a; scanf("%d",&a); spt.Insert(spt.rt,a,0); ans=a; n--; while(n--){ a=0; scanf("%d",&a); int x,y; spt.findpre(spt.rt,a,x); spt.findsucc(spt.rt,a,y); ans+=min(abs(a-x),abs(a-y)); spt.Insert(spt.rt,a,0); } printf("%d\n",ans); return 0; }