题意:
给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次。
题解:
典型的splay区间翻转+删点。
我们把数据排序,然后记录一下每个数原来的位置,然后splay建树的时候用原来的位置来对应,这样val[i].second就直接是这个数在splay中的那个节点。
(当然你也可以普通建树,然后手动记录位置)。
然后我们把要找的那个数对应的节点旋转到根,然后根左边的size+i就是当前数的答案,然后翻转一下前面的数,再删除根。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=1e5+7; 6 int n,a[N],size[N],ch[N][2],f[N],tot,root;bool rev[N]; 7 pair<int,int>val[N]; 8 9 void rev1(int x){if(!x)return;swap(ch[x][0],ch[x][1]);rev[x]^=1;} 10 11 void pb(int x){ 12 if(rev[x]){ 13 rev1(ch[x][0]); 14 rev1(ch[x][1]); 15 rev[x]=0; 16 } 17 } 18 19 void up(int x){ 20 size[x]=1; 21 if(ch[x][0])size[x]+=size[ch[x][0]]; 22 if(ch[x][1])size[x]+=size[ch[x][1]]; 23 } 24 25 void rotate(int x){ 26 int y=f[x],w=ch[y][1]==x; 27 ch[y][w]=ch[x][w^1]; 28 if(ch[x][w^1])f[ch[x][w^1]]=y; 29 if(f[y]){ 30 int z=f[y]; 31 if(ch[z][0]==y)ch[z][0]=x; 32 if(ch[z][1]==y)ch[z][1]=x; 33 } 34 f[x]=f[y];ch[x][w^1]=y;f[y]=x;up(y); 35 } 36 37 void splay(int x,int w){ 38 int s=1,i=x,y;a[1]=x; 39 while(f[i])a[++s]=i=f[i]; 40 while(s)pb(a[s--]); 41 while(f[x]!=w){ 42 y=f[x]; 43 if(f[y]!=w){if((ch[f[y]][0]==y)^(ch[y][0]==x))rotate(x);else rotate(y);} 44 rotate(x); 45 } 46 if(!w)root=x; 47 up(x); 48 } 49 50 void newnode(int &r,int fa,int k) 51 { 52 r=k,f[r]=fa,rev[r]=0,ch[r][0]=ch[r][1]=0; 53 } 54 55 void build(int &x,int l,int r,int fa){ 56 int mid=(l+r)>>1; 57 newnode(x,fa,mid); 58 if(l<mid)build(ch[x][0],l,mid-1,x); 59 if(r>mid)build(ch[x][1],mid+1,r,x); 60 up(x); 61 return; 62 } 63 64 int getmax(int x) 65 { 66 pb(x); 67 while(ch[x][1])x=ch[x][1],pb(x); 68 return x; 69 } 70 71 void delroot() 72 { 73 if(ch[root][0]) 74 { 75 int m=getmax(ch[root][0]); 76 splay(m,root); 77 ch[m][1]=ch[root][1]; 78 f[ch[root][1]]=m; 79 root=m,f[m]=0,up(m); 80 }else root=ch[root][1],f[root]=0; 81 } 82 83 int main(){ 84 while(scanf("%d",&n),n) 85 { 86 F(i,1,n)scanf("%d",&val[i].first),val[i].second=i; 87 sort(val+1,val+1+n),build(root,1,n,0); 88 F(i,1,n-1) 89 { 90 splay(val[i].second,0); 91 rev1(ch[root][0]); 92 printf("%d ",i+size[ch[root][0]]); 93 delroot(); 94 } 95 printf("%d\n",n); 96 } 97 return 0; 98 }
时间: 2024-10-20 22:03:52