[HNOI2002]营业额统计
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。
题解:平衡树;
奇怪的做法:这题f[i]范围比较小,可以直接硬上线段树,时间复杂度有保证,不会爆掉;
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<ctime> using namespace std; #define up(i,j,n) for(int i=j;i<=n;i++) #define LL long long #define pii pair<int,int> #define FILE "dealing" inline bool chkmin(int &x,int y){return x>y?(x=y,true):false;} inline bool chkmax(int &x,int y){return x<y?(x=y,true):false;} namespace IO{ char buf[1<<15],*fs,*ft; int gc(){return (fs==ft&&((ft=(fs=buf)+fread(buf,1,1<<15,stdin)),fs==ft))?0:*fs++;} int read(){ int x=0,ch=gc(),d=0; while(ch<'0'||ch>'9'){if(ch=='-')d=1;ch=gc();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} return d?-x:x; } }using namespace IO; namespace OI{ const int maxn=40000,Max(1000000+maxn+10),inf=1000000000; bool c[10000000]; int id,n; int f[maxn]; void updata(int root){c[root]=(c[root<<1]||c[root<<1|1]);} void change(int left,int right,int root){ if(left>id||right<id)return; if(left==id&&right==id){c[root]=1;return;} int mid=(left+right)>>1; change(left,mid,root<<1); change(mid+1,right,root<<1|1); updata(root); } int find(int left,int right,int root){ if(!c[root])return inf; if(left==right)return abs(id-left); int mid=(left+right)>>1; if(left>id)return c[root<<1]?find(left,mid,root<<1):find(mid+1,right,root<<1|1); if(right<id)return c[root<<1|1]?find(mid+1,right,root<<1|1):find(left,mid,root<<1); return min(find(left,mid,root<<1),find(mid+1,right,root<<1|1)); } void slove(){ n=read(); up(i,1,n)f[i]=read(); int ans=f[1]; id=f[1]+maxn; change(1,Max,1); up(i,2,n){ id=f[i]+maxn; ans+=find(1,Max,1); change(1,Max,1); } printf("%d\n",ans); } } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); using namespace OI; slove(); return 0; }