NKOJ 3884 (NOI 2005) 维修数列(Splay)
来源:互联网 发布:c语言中函数和 编辑:程序博客网 时间:2024/05/20 02:23
P3884 NOI2005维修数列
问题描述
输入格式
第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
输出格式
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
样例输入
9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
样例输出
-1
10
1
10
提示
你可以认为在任何时刻,数列中至少有 1 个数。 输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有 30 000 个数; 100%的数据中,任何时刻数列中最多含有 500 000 个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。 100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件 大小不超过 20MBytes。
Splay模板题,修改和翻转用lazy,维护区间和,考虑如何维护最大区间和,用类似线段树的方法解决即可。
注意当儿子为0时要特别小心。
代码:
#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>#define N 8000005#define max(a,b) ((a>b)?(a):(b))using namespace std;const int Inf=99999999;int n,m,A[N],L,R;int tot,rt,ls[N],rs[N],fa[N],si[N],v[N],lazy1[N],lazy2[N],lmax[N],rmax[N],Max[N],sum[N];int GM(int x,int y,int z){ if(x>=y&&x>=z)return x; if(y>=z)return y; return z;}void MT(int p){ lmax[p]=GM(lmax[ls[p]],sum[ls[p]]+v[p],sum[ls[p]]+v[p]+lmax[rs[p]]); rmax[p]=GM(rmax[rs[p]],sum[rs[p]]+v[p],sum[rs[p]]+v[p]+rmax[ls[p]]); Max[p]=GM(Max[ls[p]],Max[rs[p]],max(0,lmax[rs[p]])+max(0,rmax[ls[p]])+v[p]); sum[p]=sum[ls[p]]+sum[rs[p]]+v[p]; si[p]=si[ls[p]]+si[rs[p]]+1;}void PD(int p){ if(lazy1[p]) { swap(ls[ls[p]],rs[ls[p]]); swap(lmax[ls[p]],rmax[ls[p]]); swap(ls[rs[p]],rs[rs[p]]); swap(lmax[rs[p]],rmax[rs[p]]); lazy1[ls[p]]^=1; lazy1[rs[p]]^=1; } if(lazy2[p]!=Inf) { v[ls[p]]=v[rs[p]]=lazy2[p]; sum[ls[p]]=lazy2[p]*si[ls[p]]; sum[rs[p]]=lazy2[p]*si[rs[p]]; lmax[ls[p]]=rmax[ls[p]]=Max[ls[p]]=lazy2[p]>0?lazy2[p]*si[ls[p]]:lazy2[p]; lmax[rs[p]]=rmax[rs[p]]=Max[rs[p]]=lazy2[p]>0?lazy2[p]*si[rs[p]]:lazy2[p]; lazy2[ls[p]]=lazy2[rs[p]]=lazy2[p]; } lazy1[p]=0;lazy2[p]=Inf;}void Zig(int x){ int y=fa[x],z=fa[y]; if(y==ls[z])ls[z]=x;else rs[z]=x;fa[x]=z; ls[y]=rs[x];fa[rs[x]]=y; rs[x]=y;fa[y]=x; MT(y);MT(x);}void Zag(int x){ int y=fa[x],z=fa[y]; if(y==ls[z])ls[z]=x;else rs[z]=x;fa[x]=z; rs[y]=ls[x];fa[ls[x]]=y; ls[x]=y;fa[y]=x; MT(y);MT(x);}void Splay(int x,int t){ int y,z; while(fa[x]!=t) { y=fa[x];z=fa[y]; if(z)PD(z); if(y)PD(y); if(x)PD(x); if(z!=t) { if(y==ls[z]) { if(x==ls[y])Zig(y),Zig(x); else Zag(x),Zig(x); } else { if(x==rs[y])Zag(y),Zag(x); else Zig(x),Zag(x); } } else if(x==ls[y])Zig(x);else Zag(x); } if(!t)rt=x;}int BT(int x,int y){ if(x>y)return 0; int p=++tot; lazy2[p]=Inf; if(x==y&&x==0)L=p; if(x==y&&x==n+1)R=p; if(x<y) { int mid=x+y>>1; if(mid==0)L=p; if(mid==n+1)R=p; v[p]=A[mid]; ls[p]=BT(x,mid-1); rs[p]=BT(mid+1,y); fa[ls[p]]=p; fa[rs[p]]=p; MT(p); } else v[p]=sum[p]=lmax[p]=rmax[p]=Max[p]=A[x],si[p]=1; return p;}int Find(int k){ int p=rt; while(p) { PD(p); if(si[ls[p]]+1==k)return p; if(si[ls[p]]>=k)p=ls[p]; else k-=si[ls[p]]+1,p=rs[p]; } return p;}void INS(){ int i,x,y,a,b; scanf("%d%d",&x,&y); for(i=1;i<=y;i++)scanf("%d",&A[i]); a=Find(x+1);b=Find(x+2); Splay(a,0);Splay(b,rt); tot++; v[tot]=sum[tot]=lmax[tot]=rmax[tot]=Max[tot]=A[1]; lazy2[tot]=Inf;si[tot]=1; for(i=2;i<=y;i++) { tot++; v[tot]=A[i]; lazy2[tot]=Inf; ls[tot]=tot-1; fa[tot-1]=tot; MT(tot); } fa[tot]=b;ls[b]=tot;MT(b);MT(a);}void DEL(){ int x,y,a,b; scanf("%d%d",&x,&y); a=Find(x);b=Find(x+y+1); Splay(a,0);Splay(b,rt); fa[ls[rs[rt]]]=0; ls[rs[rt]]=0; MT(rs[rt]); MT(rt);}void CHA(){ int x,y,z,a,b,p; scanf("%d%d%d",&x,&y,&z); a=Find(x);b=Find(x+y+1); Splay(a,0);Splay(b,rt); p=ls[rs[rt]]; lazy2[p]=z; v[p]=z;sum[p]=z*si[p]; lmax[p]=rmax[p]=Max[p]=z>0?z*si[p]:z; MT(rs[rt]); MT(rt);}void REV(){ int x,y,a,b,p; scanf("%d%d",&x,&y); a=Find(x);b=Find(x+y+1); Splay(a,0);Splay(b,rt); p=ls[rs[rt]]; lazy1[p]^=1; swap(ls[p],rs[p]); swap(lmax[p],rmax[p]); MT(rs[rt]); MT(rt);}void SUM(){ int x,y,a,b; scanf("%d%d",&x,&y); a=Find(x);b=Find(x+y+1); Splay(a,0);Splay(b,rt); printf("%d\n",sum[ls[rs[rt]]]);}void MAX(){ Splay(L,0);Splay(R,rt); printf("%d\n",Max[ls[rs[rt]]]);}int main(){ int i,x,y,z;char s[15]; scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d",&A[i]); rt=BT(0,n+1); while(m--) { scanf("%s",s); if(s[2]=='S')INS(); if(s[2]=='L')DEL(); if(s[2]=='K')CHA(); if(s[2]=='V')REV(); if(s[2]=='T')SUM(); if(s[2]=='X')MAX(); }}
阅读全文
0 0
- NKOJ 3884 (NOI 2005) 维修数列(Splay)
- BZOJ 1500 [NOI 2005] 维修数列 (splay 模板)
- BZOJ 1500 NOI 2005 维修数列 Splay
- BZOJ 1500|NOI 2005|维修数列|Splay
- NOI 2005 维修数列
- [NOI2005]维修数列 (推荐 Splay tree)
- [BZOJ1500][NOI2005]维修数列(Splay)
- bzoj 1500: [NOI2005]维修数列(splay)
- [BZOJ1500][NOI2005]维修数列(splay)
- [BZOJ 1500][NOI2005]维修数列(Splay)
- [NOI2005]维修数列(Splay神题)
- bzoj1500 [NOI2005]维修数列(splay)
- [NOI 2005] 维护数列 splay
- [NOI 2005] 维修队列 (Splay 给最大连续子区间和 0rz)
- Splay Tree(伸展树)[NOI2005]维修数列
- 大视野在线测评 1500 [NOI2005]维修数列(splay)
- NOI2005 维修数列(splay)
- [NOI2005]维修数列 (Splay)
- android studio 自动导包设置
- Android_Retrofit2.0
- HDU 1232畅通工程
- Ionic3项目开发——页面跳转与参数传递
- Retrofit+EventBus+GreenDao+MVP简单小总结
- NKOJ 3884 (NOI 2005) 维修数列(Splay)
- 批量处理服务
- java将字符串写入到文本里
- 【JavaScript】原生JS实现AJAX、JSONP
- WEB 前端菜鸟,感觉很迷茫,该怎么做?
- 自定义horinatilalview
- CDOJ 1292 卿学姐种花 暴力 分块 线段树
- js根据日期计算星期几
- linux之cut命令的用法