POJ 3580 SuperMemo
阿新 • • 發佈:2017-08-23
queue 一個 取模 -1 har 組成 roo mes ace
題目:http://poj.org/problem?id=3580
題意:對一個數列進行如下操作
操作1:對區間內加一個數
操作2:對區間內進行反轉
操作3:對區間內進行平移 例如:區間內數為2 3 4,平移1次,則為 4 2 3
操作4:在x後插入一個數
操作5:刪除x
操作6:求區間內最小值
操作1,2,4,5,6都是splay的基本操作
對於操作3 我們可以先對t進行取模 然後將區間內最後t個分離出來,再插入到區間頭部
要實現這個操作,我們只需要先splay將這t個數組成的子樹分離,之後再對原樹進行splay,再把這個子樹插入到區間頭部的左子樹下就完成了
//找了好久錯,最後發現我把+=寫成了=
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #define lson i<<1 #define rson i<<1|1 using namespace std; const int N=2e5+5; const int inf=0x3f3f3f3f; int f[N],ch[N][2],sz[N],key[N],rev[N],add[N],minn[N]; int a[N]; int root,tot; inline int get(int x) { return ch[f[x]][1]==x; } void update(int x) { if (x==0) return; sz[x]=1; if (ch[x][0]) sz[x]+=sz[ch[x][0]]; if (ch[x][1]) sz[x]+=sz[ch[x][1]]; minn[x]=key[x]; if (ch[x][0]) minn[x]=min(minn[x],minn[ch[x][0]]); if (ch[x][1]) minn[x]=min(minn[x],minn[ch[x][1]]); } void pushdown(int x) { if (x==0) return; if (add[x]) { if (ch[x][0]) { int now=ch[x][0]; minn[now]+=add[x]; key[now]+=add[x]; add[now]+=add[x]; } if (ch[x][1]) { int now=ch[x][1]; minn[now]+=add[x]; key[now]+=add[x]; add[now]+=add[x]; } add[x]=0; } if (rev[x]) { if (ch[x][0]) { int now=ch[x][0]; rev[now]^=1; swap(ch[now][0],ch[now][1]); } if (ch[x][1]) { int now=ch[x][1]; rev[now]^=1; swap(ch[now][0],ch[now][1]); } rev[x]=0; } } void Rotate(int x) { pushdown(f[x]); pushdown(x); int fa=f[x],ff=f[fa],kind=get(x); ch[fa][kind]=ch[x][kind^1];f[ch[x][kind^1]]=fa; ch[x][kind^1]=fa;f[fa]=x; f[x]=ff; if (ff) ch[ff][ch[ff][1]==fa]=x; update(fa); update(x); } void splay(int x,int y) { for(int fa;(fa=f[x])!=y;Rotate(x)) if (f[fa]!=y) Rotate((get(fa)==get(x))?fa:x); if (y==0) root=x; } int build(int l,int r,int fa) { if (l>r) return 0; int mid=(l+r)>>1; int now=++tot; f[now]=fa;key[now]=minn[now]=a[mid];rev[now]=add[now]=0; ch[now][0]=build(l,mid-1,now); ch[now][1]=build(mid+1,r,now); update(now); return now; } int Find(int x) { int now=root; while(1) { pushdown(now); if (ch[now][0]&&sz[ch[now][0]]>=x) now=ch[now][0]; else { x-=sz[ch[now][0]]; if (x==1) return now; x--; now=ch[now][1]; } } } void Treaval(int x) { if(x) { pushdown(x); Treaval(ch[x][0]); printf("結點%2d:左兒子 %2d 右兒子 %2d 父結點 %2d size = %2d ,key = %2d min=%2d \n",x,ch[x][0],ch[x][1],f[x],sz[x],key[x],minn[x]); Treaval(ch[x][1]); } } void debug() {printf("%d\n",root);Treaval(root);} int main() { int n,m; while(scanf("%d",&n)!=EOF) { tot=0; a[1]=a[n+2]=inf; for(int i=1;i<=n;i++) scanf("%d",&a[i+1]); root=build(1,n+2,0); scanf("%d",&m); char s[20]; int x,y,t; while(m--) { scanf("%s",s); switch(s[0]) { case ‘A‘: { scanf("%d%d%d",&x,&y,&t); int aa=Find(x); int bb=Find(y+2); splay(aa,0); splay(bb,aa); int now=ch[ch[root][1]][0]; key[now]+=t; minn[now]+=t; add[now]+=t; update(ch[root][1]); update(root); break; } case ‘R‘: { if (s[3]==‘E‘) { scanf("%d%d",&x,&y); int aa=Find(x); int bb=Find(y+2); splay(aa,0); splay(bb,aa); int now=ch[ch[root][1]][0]; rev[now]^=1; swap(ch[now][0],ch[now][1]); } else { scanf("%d%d%d",&x,&y,&t); int len=y-x+1; t=(t%len+len)%len; if (t==0) break; int aa=Find(y-t+1); int bb=Find(y+2); splay(aa,0); splay(bb,aa); int tem=ch[ch[root][1]][0]; ch[ch[root][1]][0]=0; update(ch[root][1]); update(root); aa=Find(x); bb=Find(x+1); splay(aa,0); splay(bb,aa); ch[ch[root][1]][0]=tem; f[tem]=ch[root][1]; update(ch[root][1]); update(root); } break; } case ‘I‘: { scanf("%d%d",&x,&t); int aa=Find(x+1); int bb=Find(x+2); splay(aa,0); splay(bb,aa); int now=++tot; ch[ch[root][1]][0]=now; f[now]=ch[root][1]; key[now]=t;sz[now]=1; minn[now]=t; ch[now][0]=ch[now][1]=rev[now]=add[now]=0; update(ch[root][1]); update(root); break; } case ‘D‘: { scanf("%d",&x); int aa=Find(x); int bb=Find(x+2); splay(aa,0); splay(bb,aa); ch[ch[root][1]][0]=0; update(ch[root][1]); update(root); break; } case ‘M‘: { scanf("%d%d",&x,&y); int aa=Find(x); int bb=Find(y+2); splay(aa,0); splay(bb,aa); int now=ch[ch[root][1]][0]; //debug(); printf("%d\n",minn[now]); break; } } } } return 0; }
POJ 3580 SuperMemo