[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序機械臂
阿新 • • 發佈:2018-01-04
ace down 網上 while 題意 esp 很難 clu build
非常垃圾的一道平衡樹,結果被日了一天。很難受嗷嗷嗷
首先不得不說網上的題解讓我這個本來就不熟悉平衡樹的彩筆很難受——並不好理解。
還好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法。
題意在操作時,就是第i次把編號為i-1和編號i的後繼分別提到根和根的右兒子,根的右兒子的左子樹打上翻轉標記。
用外部數組記錄原來高度第幾大的在平衡樹中編號是多少。就可以直接操作了。
註意有相同的高度,離散化時直接按高度第一關鍵字,編號第二關鍵字就行了。
還有每次splay要把根到當前節點都pushdown一遍。還有先pushdown再繼續操作!包括判斷有沒有左右兒子!
可能只有我是傻逼吧
#include<bits/stdc++.h> usingnamespace std; const int N=200010; inline int read(){ int r=0,c=getchar(); while(!isdigit(c))c=getchar(); while(isdigit(c)) r=r*10+c-‘0‘,c=getchar(); return r; } #define ls ch[x][0] #define rs ch[x][1] int ch[N][2],siz[N],fa[N],rev[N],pos[N]; int rt,tot; struct qwq{ int v,p; }a[N];bool cmpv(qwq p,qwq q){ if(p.v==q.v)return p.p<q.p; return p.v<q.v; } bool cmpp(qwq p,qwq q){ return p.p<q.p; } void pp(int x){ siz[x]=siz[ls]+siz[rs]+1; } void pd(int x){ if(rev[x]){ rev[x]=0; swap(ls,rs); rev[ls]^=1;rev[rs]^=1; } } int get(intx){ 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[x][px^1]=y;fa[y]=x; ch[y][px]=t;fa[t]=y; if(z)ch[z][py]=x;fa[x]=z; pp(y); } int s[N]; void splay(int x,int lim){ int top=0; for(int i=x;i;i=fa[i])s[++top]=i; for(int i=top;i;i--)pd(s[i]); int y=fa[x]; while(y^lim){ if(fa[y]^lim) rotate(get(x)==get(y)?y:x); rotate(x);y=fa[x]; } rt=!lim?x:rt;pp(x); } int nxt(){ pd(rt);int x=ch[rt][1]; while(pd(x),ch[x][0])x=ch[x][0]; return x; } int build(int l,int r){ if(l>r)return 0; int mid=l+r>>1,x=++tot; ls=build(l,mid-1);fa[ls]=x; rs=build(mid+1,r);fa[rs]=x; pos[a[mid].v]=x; pp(x);return x; } int main(){ int n=read(); a[1].v=0,a[n+2].v=n+1; for(int i=2;i<=n+1;i++) a[i].v=read(),a[i].p=i; sort(a+2,a+n+2,cmpv); for(int i=2;i<=n+1;i++) a[i].v=i-1; sort(a+2,a+n+2,cmpp); rt=build(1,n+2); for(int i=1;i<=n;i++){ int x=pos[i];splay(x,0); printf("%d",siz[ls]);if(i^n)printf(" "); x=nxt(); int y=pos[i-1]; splay(y,0);splay(x,rt); rev[ls]^=1; } }
[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序機械臂