POJ 3580SuperMemo
Posted BK_201
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3580SuperMemo相关的知识,希望对你有一定的参考价值。
题目: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 3580SuperMemo的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3580 - SuperMemo - [伸展树splay]