吐槽一下,還是太弱了,這個被認為伸展樹水題的題本菜搞了好久。。。
給你n個數
每次將第i個位置到第i大的數所在位置 之間的數進行翻轉,輸出的是第i大的數所在的位置
伸展樹的節點不需要記錄任何東西,直接按照各個數在數組中的順序建樹即可(即建好伸展樹后中序遍歷的結果就是原數組的數)
所以伸展樹的節點編號的相對大小代表的是這個數在數組中的下標,這點一定要搞清楚
然后建樹的時候順便記錄下第i大的數所在的節點編號是什么。
最后每次將第i大的數旋轉到根,然后 左子樹的大小 就是在數組中相對位置在這個數的左邊的數的個數 因為每次將第i大的數翻轉到第i個位置時,這個數就不會用到了,
所以每次統計好后就直接把根節點給刪了(刪除也有點小技巧,詳見代碼),這樣的話答案就是 i+size[ch[root][0]] 了
由於並沒有提取區間的操作,所以我沒有另外加兩個節點,所以我在n==1的時候需要特判一下

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define Keytree (ch[ ch[root][1] ][0]) const int maxn = 100010; struct node { int num,id; }in[maxn]; int id[maxn]; int cmp(node a,node b){ if(a.num!=b.num) return a.num<b.num; return a.id<b.id; } struct SplayTree{ int tot,root; int pre[maxn]; int size[maxn]; int ch[maxn][2]; inline void Rotate(int x, int c) { // 旋轉, c=0 左旋, c=1 右旋 int y = pre[x]; pushdown(y); pushdown(x); ch[y][!c] = ch[x][c]; if ( ch[x][c] ) pre[ ch[x][c] ] = y; pre[x] = pre[y]; if ( pre[y] ) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; ch[x][c] = y; pre[y] = x; pushup(y); } inline void Splay(int x, int f) { // 把結點x轉到結點f的下面 pushdown(x); while ( pre[x] != f ) { int y = pre[x], z = pre[y]; pushdown(z); pushdown(y); pushdown(x); // 旋轉前必須先去除反轉標記 if ( pre[ pre[x] ] == f ) { Rotate(x, ch[pre[x]][0] == x); } else { if ( ch[z][0] == y ) { if ( ch[y][0] == x ) Rotate(y, 1), Rotate(x, 1); else Rotate(x, 0), Rotate(x, 1); } else { if ( ch[y][0] == x ) Rotate(x, 1), Rotate(x, 0); else Rotate(y, 0), Rotate(x, 0); } } } pushup(x); if ( f == 0 ) root = x; } inline void Select(int k, int f) { // 把第k個點旋轉到f的下面 int x = root; while ( 1 ) { pushdown(x); if ( k == size[ ch[x][0] ] + 1 ) break; if ( k <= size[ ch[x][0] ] ) x = ch[x][0]; else { k -= (size[ ch[x][0] ] + 1); x = ch[x][1]; } } Splay(x, f); } inline void del_root(){//刪除根節點 int t=root; if(ch[root][1]) { root=ch[root][1]; Select(1,0);//把右子樹中序遍歷的第一個點旋轉到根(因為這個點的左兒子肯定為空) ch[root][0]=ch[t][0];//將原先根節點的左子樹接到當前根節點的左子樹上 if(ch[t][0]) pre[ch[t][0]]=root; } else root=ch[root][0]; pre[root]=0; pushup(root); } inline void pushup(int x){ size[x]=size[ ch[x][0] ] + size[ ch[x][1] ] +1; } inline void pushdown(int x){ if(flip[x]){ flip[x]=0; flip[ch[x][0]]^=1; flip[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]); } } void Newnode(int &x,int f){ x=++tot; pre[x]=f; ch[x][0]=ch[x][1]=0; flip[x]=0; size[x]=1; } void build(int &x,int l,int r,int f){ if(l>r) return ; int mid=(l+r)>>1; Newnode(x,f); map[id[mid]]=x; build(ch[x][0],l,mid-1,x); build(ch[x][1],mid+1,r,x); pushup(x); } void init(int n){ int i; pre[0]=ch[0][0]=ch[0][1]=0; size[0]=flip[0]=tot=0; for(i=1;i<=n;i++) { scanf("%d",&in[i].num); in[i].id=i; } sort(in+1,in+n+1,cmp); for(i=1;i<=n;i++) id[in[i].id]=i; map[id[1]] = 1; map[id[n]] = 2; Newnode(root,0); Newnode(ch[root][1],root); build(Keytree,2,n-1,ch[root][1]); pushup(ch[root][1]); pushup(root); } void solve(int n){ for(int i=1;i<=n;i++){ Splay(map[i],0); printf("%d",i+size[ch[root][0]]); if(i<n) printf(" "); flip[ch[root][0]]^=1; del_root(); } puts(""); } int map[maxn]; int flip[maxn]; }spt; int main(){ int n; while(scanf("%d",&n),n) { if(n==1) {scanf("%*d");printf("1\n");continue;} spt.init(n); spt.solve(n); } return 0; }