[BZOJ 1588][HNOI2002]营业额统计(Splay)
Posted Zars19
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 1588][HNOI2002]营业额统计(Splay)相关的知识,希望对你有一定的参考价值。
Description
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。
Solution
用Splay维护,每插入一个值,如果w==1就找前驱和后继来确定最小波动值
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #define lc(x) t[x].ch[0] #define rc(x) t[x].ch[1] #define Min(a,b) (a<b?a:b) #define Abs(x) (x>=0?x:-x) #define INF 0x3f3f3f3f; using namespace std; int n,root,siz=0,sum=0; struct Node{ int ch[2],father,val,w,siz; Node(){ch[0]=ch[1]=father=val=w=siz=0;} }t[40000]; int Read() { int x=0,f=1;char c=getchar(); while(c<‘0‘||c>‘9‘){ if(c==‘-‘)f=-1;c=getchar(); } while(c>=‘0‘&&c<=‘9‘){ x=x*10+c-‘0‘;c=getchar(); } return x*f; } void Update(int x) { t[x].siz=t[lc(x)].siz+t[rc(x)].siz+t[x].w; } void Rotate(int x,int &k) { int y=t[x].father; int z=t[y].father; int p=(t[y].ch[0]==x)?0:1; if(y==k)k=x; else { if(t[z].ch[0]==y)t[z].ch[0]=x; else t[z].ch[1]=x; } t[x].father=z; t[y].ch[p]=t[x].ch[p^1]; t[t[x].ch[p^1]].father=y; t[x].ch[p^1]=y; t[y].father=x; Update(y),Update(x); } void Splay(int x,int &k) { while(k!=x) { int y=t[x].father; int z=t[y].father; if(y!=k) { if((t[y].ch[0]==x)^(t[z].ch[0]==y)) Rotate(x,k); else Rotate(y,k); } Rotate(x,k); } } void Insert(int &x,int k,int f) { if(!x) { ++siz;x=siz; t[x].father=f; t[x].w=t[x].siz=1; t[x].val=k; Splay(x,root); return; } t[x].siz++; if(k<t[x].val)Insert(t[x].ch[0],k,x); else if(k>t[x].val) Insert(t[x].ch[1],k,x); else t[x].w++,Splay(x,root); } int Pre() { int p=t[root].ch[0]; if(!p)return INF; while(t[p].ch[1]) p=t[p].ch[1]; return t[p].val; } int Suc() { int p=t[root].ch[1]; if(!p)return INF; while(t[p].ch[0]) p=t[p].ch[0]; return t[p].val; } int main() { n=Read(); for(int i=1;i<=n;i++) { int x=Read(); Insert(root,x,0); if(i==1) { sum+=x; continue; } if(t[root].w==1) { int a=x-Pre(),b=x-Suc(); a=Abs(a),b=Abs(b); sum+=Min(a,b); } } printf("%d\n",sum); return 0; }
以上是关于[BZOJ 1588][HNOI2002]营业额统计(Splay)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1588: [HNOI2002]营业额统计 treap