BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap
Posted Meek
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap相关的知识,希望对你有一定的参考价值。
1588: [HNOI2002]营业额统计
Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
5
1
2
5
4
6
Sample Output
HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
该题数据bug已修复.----2016.5.15
题解:
双向链表:http://www.open-open.com/doc/view/a46375420b6a43f08e0862489069a11d
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<queue> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) typedef long long LL; const LL INF = (1LL<<60)-1; const double Pi = acos(-1.0); const int N = 1e5+10, M = 1e6+11, mod = 1e9+7, inf = (1<<30)-1; struct ss {int x,id; bool operator < (const ss &r) const { return x<r.x; } }a[N]; int ans,n,Rank[N],lef[N],righ[N]; int main() { scanf("%d",&n); for(int i = 1; i <= n; ++i) scanf("%d",&a[i].x),a[i].id=i; ans = a[1].x; sort(a+1,a+n+1); for(int i = 1; i <= n; ++i) Rank[a[i].id] = i; for(int i = 1; i <= n; ++i) lef[i] = i-1, righ[i] = i+1; righ[n] = 0; for(int i = n; i >=1; --i) { int x = Rank[i]; if(lef[x] && righ[x]) { ans += min(a[x].x - a[lef[x]].x,a[righ[x]].x - a[x].x); righ[lef[x]] = righ[x]; lef[righ[x]] = lef[x]; } else if(!lef[x] && righ[x]) { ans += a[righ[x]].x - a[x].x; lef[righ[x]] = 0; } else if(!righ[x] && lef[x]){ ans += a[x].x - a[lef[x]].x; righ[lef[x]] = 0; } } printf("%d\\n",ans); }
treap写法
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<queue> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) typedef long long LL; const LL INF = (1LL<<60)-1; const double Pi = acos(-1.0); const int N = 1e5+10, M = 1e6+11, mod = 1e9+7, inf = (1<<30)-1; struct data {int l,r,v,size,rnd,w;}tr[N * 20]; int n,size=0,root,ans,Ans; void update(int k) {tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;} void rturn (int &k){ int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k; tr[t].size=tr[k].size;update(k);k=t; } void lturn(int &k) { int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k; tr[t].size=tr[k].size;update(k);k=t; } void insert(int &k,int x) { if(k == 0) { size++;k=size; tr[k].size=tr[k].w=1; tr[k].v=x; tr[k].rnd=rand(); return ; } tr[k].size++; if(tr[k].v == x) tr[k].w++; else if(x > tr[k].v) { insert(tr[k].r,x); if(tr[tr[k].r].rnd<tr[k].rnd) lturn(k); } else { insert(tr[k].l,x); if(tr[tr[k].l].rnd<tr[k].rnd) rturn(k); } } void query_pre(int k,int x) { if(k == 0) return ; if(tr[k].v <= x) { ans=tr[k].v;query_pre(tr[k].r,x); } else query_pre(tr[k].l,x); } void query_nex(int k,int x) { if(k == 0) return ; if(tr[k].v >= x) { ans=tr[k].v;;query_nex(tr[k].l,x); } else query_nex(tr[k].r,x); } int main() { root = 0; scanf("%d",&n); for(int i = 1; i <= n; ++i) { int x; scanf("%d",&x); if(i == 1) { Ans = x; } else { ans = -inf;query_pre(root,x); int fi = ans; ans = inf;query_nex(root,x); int se = ans; //cout<<fi<<" "<<se<<endl; if(fi!=-inf || se != inf) Ans += min(x-fi,se-x); } insert(root,x); } printf("%d\\n",Ans); return 0; }
splay(HZWER)
#include<iostream> #include<cstdio> #define inf 1000000000 using namespace std; int ans,n,t1,t2,rt,size; int tr[50001][2],fa[50001],num[50001]; void rotate(int x,int &k) { int y=fa[x],z=fa[y],l,r; if(tr[y][0]==x)l=0;else l=1;r=l^1; if(y==k)k=x; else{if(tr[z][0]==y)tr[z][0]=x;else tr[z][1]=x;} fa[x]=z;fa[y]=x;fa[tr[x][r]]=y; tr[y][l]=tr[x][r];tr[x][r]=y; } void splay(int x,int &k) { int y,z; while(x!=k) { y=fa[x],z=fa[y]; if(y!=k) { if((tr[y][0]==x)^(tr[z][0]==y))rotate(x,k); else rotate(y,k); } rotate(x,k); } } void ins(int &k,int x,int last) { if(k==0){size++;k=size;num[k]=x;fa[k]=last;splay(k,rt);return;} if(x<num[k])ins(tr[k][0],x,k); else ins(tr[k][1],x,k); } void ask_before(int k,int x) { if(k==0)return; if(num[k]<=x){t1=num[k];ask_before(tr[k][1],x);} else ask_before(tr[k][0],x); } void ask_after(int k,int x) { if(k==0)return; if(num[k]>=x){t2=num[k];ask_after(tr[k][0],x);} else ask_after(tr[k][1],x); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int x;if(scanf("%d",&x)==EOF)x=0; t1=-inf;t2=inf; ask_before(rt,x); ask_after(rt,x); if(i!=1)ans+=min(x-t1,t2-x); else ans+=x; ins(rt,x,0); } printf("%d",ans); return 0; }
以上是关于BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1588: [HNOI2002]营业额统计 treap