BZOJ_1552_[Cerc2007]robotic sort_splay
BZOJ_1552_[Cerc2007]robotic sort_splay
题意:
分析:
splay维护区间操作
可以先把编号排序,给每个编号分配一个固定的点,映射过去
查找编号的排名时先找到这个点,找出到根的路径
从上至下pushdown标记,顺便求出这个点的排名
然后翻转啥的就好做了
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 100050 #define ls ch[p][0] #define rs ch[p][1] #define get(x) (ch[f[x]][1]==x) int a[N],ch[N][2],f[N],siz[N],val[N],turn[N],rt; int n,w[N]; struct A{ int num,id; }b[N]; bool cmp(const A &x,const A &y) { if(x.num==y.num)return x.id<y.id; return x.num<y.num; } void print(int p) { if(!p)return ; if(ls)print(ls); printf("p=%d ,val[p]=%d ",p,val[p]); if(rs)print(rs); } void pushup(int p){ if(p) siz[p]=siz[ls]+siz[rs]+1; } void pushdown(int p) { if(turn[p]) { turn[p]=0; turn[ls]^=1;turn[rs]^=1; swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]); } } void rotate(int x) { int y=f[x],z=f[y],k=get(x); ch[y][k]=ch[x][k^1];f[ch[y][k]]=y;ch[x][k^1]=y; f[y]=x;f[x]=z;if(z)ch[z][ch[z][1]==y]=x; pushup(y),pushup(x);if(rt==y)rt=x; } void splay(int x,int y) { for(int fa;(fa=f[x])!=y;rotate(x)) if(f[fa]!=y) rotate((get(x)==get(fa)) ? fa : x); } int find(int x) { int p=rt; while(1){ pushdown(p); if(x<=siz[ls])p=ls; else{ x-=siz[ls]+1; if(!x)return p; p=rs; } } } void build(int fa,int l,int r,int flg) { if(l>r)return ; int mid=l+r>>1; ch[fa][flg]=mid; f[mid]=fa; siz[mid]=1; val[mid]=a[mid-1]; w[a[mid-1]]=mid; build(mid,l,mid-1,0); build(mid,mid+1,r,1); pushup(mid); } int getrank(int p) { int cnt=0; while(p) { a[++cnt]=p; p=f[p]; } int i; for(i=cnt;i;i--) pushdown(a[i]); splay(a[1],0); return siz[ch[a[1]][0]]; } void reverse(int x,int p) { x=find(x); p=find(p); splay(x,0); splay(p,rt); turn[ls]=1; swap(ch[ls][0],ch[ls][1]); pushup(p);pushup(x); } int main() { scanf("%d",&n); int i; for(i=1;i<=n;i++) { scanf("%d",&b[i].num); b[i].id=i; } sort(b+1,b+n+1,cmp); for(i=1;i<=n;i++) { a[b[i].id]=i; } build(0,1,n+2,1); rt=n+3>>1; for(i=1;i<=n;i++) { int tmp=getrank(w[i]); if(i-1)printf(" %d",tmp); else printf("%d",tmp); reverse(i,tmp+2); } }