[bzoj1861][Zjoi2006]Book书架
我写的非常shi,还巨tm慢,不过。。。很好理解qwq
题意:给编号为1~n的书,支持操作:
1.把编号为x的放在第一个
2.放在最后一个
3.上移一个或下移一个或不动
4.询问编号为x的在第几个
5.第x个编号是几
我的方法是一直给每个点一个权值,以权值为关键字维护splay,这样和普通平衡树一样了。所以说好像可以set水过?
要记录编号为x的权值是几。查询直接查,移动时候先删除,再把权值修改成合适的值(第一个就修改成最小值-1,往前一个就修改成前驱和前驱的前驱中间值,类似)。
顺便每个节点维护一下编号就好了。。
#include<bits/stdc++.h> #define eps 1e-10 using namespace std; const int N=200010; typedef double ff; inline int read(){ int r=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){r=r*10+c-'0';c=getchar();} return r*f; } int ch[N][2],siz[N],fa[N],f[N]; ff pos[N],w[N]; int rt,tot,now; void pp(int x){ siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } int get(int x){ return x==ch[fa[x]][1]; } void rotate(int x){ int y=fa[x],z=fa[y],px=get(x),py=get(y); int t=ch[x][px^1]; ch[y][px]=t;fa[t]=y; ch[x][px^1]=y;fa[y]=x; ch[z][py]=x;fa[x]=z; pp(y); } void splay(int x){ int y=fa[x]; while(y){ if(fa[y]) rotate(get(x)==get(y)?y:x); rotate(x);y=fa[x]; } pp(x);rt=x; } ff minn(){ int x=rt; while(ch[x][0])x=ch[x][0]; return w[x]; } ff maxx(){ int x=rt; while(ch[x][1])x=ch[x][1]; return w[x]; } int pre(){ int x=ch[rt][0]; while(ch[x][1])x=ch[x][1]; return x; } int nxt(){ int x=ch[rt][1]; while(ch[x][0])x=ch[x][0]; return x; } int qnum(int rk){ int x=rt; while(1){ int y=ch[x][0]; if(y&&siz[y]>=rk)x=y; else{ rk-=(y?siz[y]:0)+1; if(rk<=0){ splay(x);return f[x]; } x=ch[x][1]; } } } int qrank(ff val){ int x=rt; while(abs(w[x]-val)>eps) x=ch[x][val>w[x]]; splay(x); return siz[ch[x][0]]; } void ins(ff val){ if(!rt){ rt=++tot;w[tot]=val; siz[tot]=1;f[tot]=now; return; } int x=rt; while(1){ int y=ch[x][0]; y=x,x=ch[x][val>w[x]]; if(!x){ w[++tot]=val; ch[y][val>w[y]]=tot;fa[tot]=y; siz[tot]=1;f[tot]=now;splay(tot); return; } } } void del(ff val){ qrank(val); if(!ch[rt][0]&&!ch[rt][1]){ rt=0;return; } int x=-1; x=ch[rt][0]?x:1; x=ch[rt][1]?x:0; if(~x){ rt=ch[rt][x];fa[rt]=0; return; } x=ch[rt][1]; splay(pre()); ch[rt][1]=x,fa[x]=rt; pp(rt); } void dfs(int x){ if(!x)return; dfs(ch[x][0]); printf("%.0f ",w[x]); dfs(ch[x][1]); } int main(){ int n=read(),m=read(); for(int i=1;i<=n;i++) now=read(),ins(i*1000),pos[now]=i*1000; while(m--){ char s[10];scanf("%s",s); if(s[0]=='T'){ int x=read(),y=minn(); del(pos[x]); now=x;ins(y-1000); pos[x]=y-1000; } else if(s[0]=='B'){ int x=read(),y=maxx(); del(pos[x]); now=x;ins(y+1000); pos[x]=y+1000; } else if(s[0]=='I'){ int x=read(),o=read(); if(!o)continue; ff t=pos[x],v;int y,z; if(~o){ qrank(t);int y=pre(); if(abs(w[y]-minn())>eps){ splay(y);z=pre(); v=(w[y]+w[z])/2; } else v=w[y]-1000; pos[x]=v;now=x;ins(v); } else{ qrank(t);int y=nxt(); if(abs(w[y]-maxx())>eps){ splay(y);z=nxt(); v=(w[y]+w[z])/2; } else v=w[y]+1000; pos[x]=v;now=x;ins(v); } } else if(s[0]=='A'){ printf("%d\n",qrank(pos[read()])); } else{ printf("%d\n",qnum(read())); } } } /* 10 10 1 3 2 7 5 8 10 4 9 6 Query 3 Top 5 Ask 6 Bottom 3 Ask 3 Top 6 Insert 4 -1 Query 5 Query 2 Ask 2 */
想了想真的可以set水掉= =