維護序列[Splay]
阿新 • • 發佈:2018-12-15
題目描述
請寫一個程式,要求維護一個數列,支援以下 6 種操作:(請注意,格式欄 中的下劃線‘ _ ’表示實際輸入檔案中的空格)
輸入格式:
輸入檔案的第 1 行包含兩個數 N 和 M,N 表示初始時數列中數的個數,M 表示要進行的運算元目。 第 2 行包含 N 個數字,描述初始時的數列。 以下 M 行,每行一條命令,格式參見問題描述中的表格
輸出格式:
對於輸入資料中的 GET-SUM 和 MAX-SUM 操作,向輸出檔案依次列印結 果,每個答案(數字)佔一行。
輸入樣例#1:
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:
-1 10 1 10
說明
你可以認為在任何時刻,數列中至少有 1 個數。
輸入資料一定是正確的,即指定位置的數在數列中一定存在。
50%的資料中,任何時刻數列中最多含有 30 000 個數;
100%的資料中,任何時刻數列中最多含有 500 000 個數。
100%的資料中,任何時刻數列中任何一個數字均在[-1 000, 1 000]內。
100%的資料中,M ≤20 000,插入的數字總數不超過 4 000 000 。
Splay模板 + 類似線段樹區間合併的東西
#include<bits/stdc++.h> #define N 5000005 #define lc t[x].ch[0] #define rc t[x].ch[1] using namespace std; int n,m,root,tot,a[N],p[N]; char ch[20]; struct Node{ int ch[2],fa,val,size; int tag,lazy; int lmax,rmax,Max,sum; }t[N]; int read(){ int cnt=0,f=1;char ch=0; while(!isdigit(ch)){ch=getchar();if(ch=='-')f=-1;} while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar(); return cnt*f; } void Update(int x,int d){ t[x].val=d,t[x].sum=d*t[x].size,t[x].lazy+=d; t[x].lmax=t[x].rmax=t[x].Max=max(d,d*t[x].size); } void Pushup(int x){ t[x].size=t[lc].size+t[rc].size+1; t[x].sum=t[lc].sum+t[x].val+t[rc].sum; t[x].Max=max( max(t[lc].Max,t[rc].Max) , max(t[lc].rmax,0) + t[x].val + max(0,t[rc].lmax) ); t[x].lmax=max(t[lc].lmax,t[lc].sum + t[x].val + max(0,t[rc].lmax)); t[x].rmax=max(t[rc].rmax,t[rc].sum + t[x].val + max(0,t[lc].rmax)); } int Build(int l,int r,int fa){ if(l>r) return 0; int mid=(l+r)>>1,x=++tot; p[x]=mid; t[x].size=1; t[x].fa=fa,t[x].lmax=t[x].rmax=t[x].Max=t[x].sum=t[x].val=a[mid]; lc=Build(l,mid-1,x),rc=Build(mid+1,r,x); Pushup(x); return x; } void Swap(int x){ swap(lc,rc); swap(t[x].lmax,t[x].rmax); t[x].tag^=1; } void Pushdown(int x){ if(t[x].tag){ if(lc) Swap(lc); if(rc) Swap(rc); t[x].tag=0; } if(t[x].lazy){ if(lc) Update(lc,t[x].lazy); if(rc) Update(rc,t[x].lazy); t[x].lazy=0; } } void Pushpath(int x){ if(t[x].fa) Pushpath(t[x].fa); Pushdown(x); } void rotate(int x){ int y=t[x].fa,z=t[y].fa; int k=(t[y].ch[1]==x); t[z].ch[t[z].ch[1]==y]=x; t[x].fa=z; t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].fa=y; t[x].ch[k^1]=y; t[y].fa=x; Pushup(y),Pushup(x); } void Splay(int x,int goal){ Pushpath(x); while(t[x].fa!=goal){ int y=t[x].fa,z=t[y].fa; if(z!=goal) (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y); rotate(x); }if(goal==0) root=x; } int Find(int x,int k){ Pushdown(x); if(t[lc].size>=k) return Find(lc,k); else if(t[lc].size+1<k) return Find(rc,k-t[lc].size-1); return x; } int main(){ n=read(),m=read(); for(int i=2;i<=n+1;i++) a[i]=read(); a[1]=a[n+2]=-0x3fffffff; root=Build(1,n+2,0); while(m--){ scanf("%s",ch); if(ch[0]=='I'){ int x=read(),T=read(); x=Find(root,x+1); Splay(x,0); int y=Find(rc,1); Splay(y,x); for(int i=1;i<=T;i++) a[i]=read(); int o=Build(1,T,y); t[y].ch[0]=o; Pushup(y),Pushup(x); } if(ch[0]=='D'){ int x=read(),T=read(); x=Find(root,x); Splay(x,0); int y=Find(rc,T+1); Splay(y,x); t[t[y].ch[0]].fa=0,t[y].ch[0]=0; Pushup(y),Pushup(x); } if(ch[2]=='K'){ int x=read(),T=read(),val=read(); x=Find(root,x); Splay(x,0); int y=Find(rc,T+1); Splay(y,x); Update(t[y].ch[0],val); Pushup(y),Pushup(x); } if(ch[0]=='R'){ int x=read(),T=read(); x=Find(root,x); Splay(x,0); int y=Find(rc,T+1); Splay(y,x); Swap(t[y].ch[0]); t[t[y].ch[0]].tag^=1; Pushup(y),Pushup(x); } if(ch[0]=='G'){ int x=read(),T=read(); x=Find(root,x); Splay(x,0); int y=Find(rc,T+1); Splay(y,x); printf("%d\n",t[t[y].ch[0]].sum); } if(ch[2]=='X') printf("%d\n",t[root].Max); } return 0; }