bzoj 1552
首先用splay维护嘛
然后查询的时候就把对应的节点转到根,左子树大小就是排名
然后再做个区间翻转即可
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> using namespace std; struct node { int v,num; friend bool operator < (node a,node b) { return a.v==b.v?a.num<b.num:a.v<b.v; } }p[100005]; int ch[100005][2]; int siz[100005]; int a[100005]; int f[100005]; int fl[100005]; int rot; int n; void pushdown(int x) { if(fl[x]) { swap(ch[ch[x][0]][0],ch[ch[x][0]][1]),fl[ch[x][0]]^=1; swap(ch[ch[x][1]][0],ch[ch[x][1]][1]),fl[ch[x][1]]^=1; fl[x]=0; } } void update(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } void rotate(int x) { int y=f[x],z=f[y],k=(ch[y][1]==x); ch[z][ch[z][1]==y]=x,f[x]=z; ch[y][k]=ch[x][!k],f[ch[x][!k]]=y; ch[x][!k]=y,f[y]=x; update(y),update(x); } void dfs_pushdown(int x) { if(!x)return; dfs_pushdown(f[x]); pushdown(x); } void splay(int x,int ed) { dfs_pushdown(x); while(f[x]!=ed) { int y=f[x],z=f[y]; if(z!=ed) { if((ch[y][1]==x)^(ch[z][1]==y))rotate(x); else rotate(y); } rotate(x); } if(!ed)rot=x; } int get_pos(int x,int k) { pushdown(x); if(siz[ch[x][0]]>=k)return get_pos(ch[x][0],k); else if(siz[ch[x][0]]+1<k)return get_pos(ch[x][1],k-1-siz[ch[x][0]]); else return x; } int split(int l,int r) { int v1=get_pos(rot,l-1),v2=get_pos(rot,r+1); splay(v1,0),splay(v2,v1); return ch[v2][0]; } void rever(int l,int r) { int p=split(l,r); swap(ch[p][0],ch[p][1]),fl[p]^=1; } int buildtree(int l,int r,int fa) { int mid=(l+r)>>1; f[a[mid]]=a[fa]; fl[a[mid]]=0; if(l==r){fl[a[mid]]=0;ch[a[mid]][0]=ch[a[mid]][1]=0;siz[a[mid]]=1;return a[mid];} if(l<mid)ch[a[mid]][0]=buildtree(l,mid-1,mid); else ch[a[mid]][0]=0; if(r>mid)ch[a[mid]][1]=buildtree(mid+1,r,mid); else ch[a[mid]][1]=0; update(a[mid]); return a[mid]; } int query(int x) { splay(x,0); return siz[ch[x][0]]; } int main() { while(1) { scanf("%d",&n); if(!n)return 0; for(int i=1;i<=n;i++)scanf("%d",&p[i].v),p[i].num=i; sort(p+1,p+n+1); for(int i=1;i<=n;i++)a[p[i].num+1]=i+1; a[1]=1,a[n+2]=n+2; rot=buildtree(1,n+2,0); for(int i=1;i<=n;i++) { int t=query(i+1); if(t>i)rever(i+1,t+1); printf("%d ",t); } printf("\n"); } return 0; }