【Splay】bzoj1500(听说此题多码上几遍就能不惧任何平衡树题)
1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 15112 Solved: 4996
[Submit][Status][Discuss]
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
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
Sample Output
-1
10
1
10
10
1
10
HINT
题解
用Splay进行区间操作的话,就要先把区间的l-1的位置旋转到根,再把r+1旋转成根的子节点
然后r+1的左子树即为所求区间
代码
//by 减维 #include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> #include<map> #include<bitset> #include<algorithm> #define ll long long #define maxn 500005 #define ls son[x][0] #define rs son[x][1] #define inf 1<<29 using namespace std; int n,m,rt,sz,siz[maxn],son[maxn][2],val[maxn],lm[maxn],rm[maxn],ma[maxn],sum[maxn]; int a[maxn],fa[maxn],cov[maxn],mark[maxn]; char ch[25]; queue<int>q; bool pd(int x){return son[fa[x]][1]==x;} void upda(int x) { if(!x)return ; siz[x]=siz[son[x][0]]+siz[son[x][1]]+1; sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x]; ma[x]=max(max(0,rm[son[x][0]])+val[x]+max(0,lm[son[x][1]]),max(ma[son[x][0]],ma[son[x][1]])); lm[x]=max(sum[son[x][0]]+val[x]+max(0,lm[son[x][1]]),lm[son[x][0]]); rm[x]=max(sum[son[x][1]]+val[x]+max(0,rm[son[x][0]]),rm[son[x][1]]); } int newnode(int v) { int s; if(!q.empty()) s=q.front(),q.pop(); else s=++sz; siz[s]=1;son[s][0]=son[s][1]=fa[s]=mark[s]=0; val[s]=sum[s]=ma[s]=lm[s]=rm[s]=v; cov[s]=-inf; return s; } void rotate(int x) { int f=fa[x],g=fa[f],o=pd(x); if(g)son[g][pd(f)]=x; fa[x]=g; son[f][o]=son[x][!o]; fa[son[f][o]]=f; fa[f]=x;son[x][!o]=f; upda(f);upda(x); } void splay(int x,int tar) { for(;fa[x]!=tar;rotate(x)) if(fa[fa[x]]!=tar)rotate(pd(fa[x])==pd(x)?fa[x]:x); if(tar==0)rt=x; } int build(int l,int r) { if(l>r)return 0; int mid=(l+r)>>1; int v=a[mid]; int now=newnode(v); son[now][0]=build(l,mid-1); son[now][1]=build(mid+1,r); if(son[now][0])fa[son[now][0]]=now; if(son[now][1])fa[son[now][1]]=now; upda(now); return now; } void cover(int x,int v) { if(!x)return ; cov[x]=val[x]=v; sum[x]=v*siz[x]; lm[x]=rm[x]=ma[x]=max(v,sum[x]); } void rever(int x) { if(!x)return ; mark[x]^=1; swap(son[x][0],son[x][1]); swap(lm[x],rm[x]); } void pud(int x) { if(!x)return ; if(mark[x]){ if(son[x][0])rever(son[x][0]); if(son[x][1])rever(son[x][1]); mark[x]=0; } if(cov[x]!=-inf){ if(son[x][0])cover(son[x][0],cov[x]); if(son[x][1])cover(son[x][1],cov[x]); cov[x]=-inf; } } int kth(int k) { int x=rt; while(1) { pud(x); if(k<=siz[son[x][0]]) x=son[x][0]; else if(k==siz[son[x][0]]+1) return x; else k-=siz[son[x][0]]+1,x=son[x][1]; } } void ins() { int pos,num; scanf("%d%d",&pos,&num); int l=kth(pos+1),r=kth(pos+2); splay(l,0); splay(r,l); for(int i=1;i<=num;++i)scanf("%d",&a[i]); int z=build(1,num); fa[z]=r; son[r][0]=z; upda(z),upda(r),upda(l); } void delt(int &x) { if(!x)return ; q.push(x); delt(son[x][0]); delt(son[x][1]); x=0; } void del() { int pos,num; scanf("%d%d",&pos,&num); int l=kth(pos),r=kth(pos+num+1); splay(l,0);splay(r,l); delt(son[r][0]); upda(r),upda(l); } void change() { int pos,num,v; scanf("%d%d%d",&pos,&num,&v); int l=kth(pos),r=kth(pos+num+1); splay(l,0);splay(r,l); cover(son[r][0],v); upda(r),upda(l); } void rev() { int pos,num; scanf("%d%d",&pos,&num); int l=kth(pos),r=kth(pos+num+1); splay(l,0);splay(r,l); rever(son[r][0]); upda(r),upda(l); } void gsum() { int pos,num; scanf("%d%d",&pos,&num); int l=kth(pos),r=kth(pos+num+1); splay(l,0);splay(r,l); printf("%d\n",sum[son[r][0]]); } void dfs(int x) { if(!x)return ; pud(x); dfs(son[x][0]); printf("%d ",ma[x]); dfs(son[x][1]); } void dfs2(int x) { if(!x)return ; pud(x); dfs2(son[x][0]); printf("%d ",val[x]); dfs2(son[x][1]); } int main() { scanf("%d%d",&n,&m); for(int i=2;i<=n+1;++i)scanf("%d",&a[i]);a[1]=a[n+2]=-inf; siz[0]=mark[0]=fa[0]=son[0][0]=son[0][1]=0; val[0]=ma[0]=lm[0]=rm[0]=-inf; rt=build(1,n+2); for(int i=1;i<=m;++i) { scanf("%s",ch); if(ch[0]=='M'&&ch[2]=='X'){ printf("%d\n",ma[rt]); continue; } switch(ch[0]){ case 'I':ins();break; case 'D':del();break; case 'M':change();break; case 'R':rev();break; case 'G':gsum();break; } } return 0; }