[CQOI2014]排序機械臂
阿新 • • 發佈:2018-11-06
[CQOI2014]排序機械臂
BZOJ
luogu
可以直接預處理出操作序列的下標,
相當於支援每次查詢某個下標的排名以及區間翻轉
對於詢問可以額外記錄fa,利用平衡樹性質暴力跳fa求rank
區間翻轉可以用fhq_treap,很短
#include<bits/stdc++.h> using namespace std; const int _=1e5+5; int re(){ int x=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*w; } struct node{int v,id;}s[_]; int n,rt,top,fix[_],sz[_],fa[_],ls[_],rs[_],rev[_],st[_]; bool cmp(node a,node b){return a.v<b.v||(a.v==b.v&&a.id<b.id);} void rever(int x){rev[x]^=1;swap(ls[x],rs[x]);} void pd(int x){ if(rev[x])rever(ls[x]),rever(rs[x]),rev[x]=0; } void pu(int x){sz[x]=sz[ls[x]]+sz[rs[x]]+1;fa[ls[x]]=x;fa[rs[x]]=x;} void merge(int&x,int l,int r){ if(!l||!r){x=l|r;return;}pd(l);pd(r); if(fix[l]>fix[r]){x=l;merge(rs[x],rs[l],r);} else{x=r;merge(ls[x],l,ls[r]);}pu(x); } void split(int x,int&l,int&r,int k){ if(!x){l=r=0;return;}pd(x); if(k>=sz[ls[x]]+1){l=x;split(rs[l],rs[x],r,k-sz[ls[x]]-1);pu(l);} else{r=x;split(ls[r],l,ls[x],k);pu(r);} } int rk(int u){ st[top=1]=u; for(int i=u;fa[i];i=fa[i])st[++top]=fa[i]; while(top)pd(st[top--]); int res=sz[ls[u]]; while(u){if(u==rs[fa[u]])res+=sz[ls[fa[u]]]+1;u=fa[u];} return res+1; } void reverse(int l,int r){ int x,y,z;split(rt,x,y,r);split(x,x,z,l-1); rever(z);merge(x,x,z);merge(rt,x,y); } int main(){ srand(time(NULL)); n=re(); for(int i=1;i<=n;i++){ s[i]=(node){re(),i};sz[i]=1; fix[i]=rand();merge(rt,rt,i); } sort(s+1,s+n+1,cmp); for(int i=1;i<=n;i++){ int k=rk(s[i].id);printf("%d ",k);reverse(i,k); } return 0; }