1. 程式人生 > >【CQOI2014】排序機械臂

【CQOI2014】排序機械臂

Description

這裡寫圖片描述

Solution

用什麼

剛看到這道題,哎呀,信心大增:序列的翻轉不就是用splay嗎!
如果不會splay,詳見splay複習小計

怎麼做

序列的翻轉直接把子樹的所有左右兒子調換即可。
然後先排一個序,找到每次要找的數他的位置(splay改變的只是樹上的位置,他的下標就是原來的位置),然後把這個數旋轉到根節點,輸出答案(他目前在樹上的位置是他在根節點是左子樹的個數+1,注意每次+1要改成+i,因為前面刪去了i-1個數)。
接著就要把這個點root刪除了,發現直接刪除不行,那麼我們先找到root右子樹中的最左邊的一個點x,其實目前的序列中root的右邊就是x。找到這個x之後,把x旋轉到根節點上,然後把root的做節點與x相連,因為現在root肯定沒有右節點,所以不用管右邊,那麼現在就把x刪除掉了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100007;
int i,j,k,l,n,m,t[maxn][2],size[maxn],f[maxn],root,mi[maxn],w[maxn];
int a[maxn],ans[maxn],biao[maxn],d[maxn];
struct
node{ int a,b; }b[maxn]; bool cmp(node x,node y){ return x.a<y.a||x.a==y.a&&x.b<y.b; } bool son(int x){ if(t[f[x]][0]==x)return 0;return 1; } void back(int x){ biao[x]^=1;swap(t[x][0],t[x][1]); } void down(int x){ if(biao[x]){ if(t[x][0])back(t[x][0]); if
(t[x][1])back(t[x][1]); biao[x]=0; } } void update(int x){ size[x]=size[t[x][0]]+size[t[x][1]]+1; } void rotate(int x){ int y=f[x],z=son(x); t[y][z]=t[x][1-z]; if(t[x][1-z])f[t[x][1-z]]=y;f[x]=f[y]; if(f[x])t[f[x]][son(y)]=x; f[y]=x;t[x][1-z]=y; update(y);update(x); } void remove(int x,int y){ if(x==y)return; do{ d[++d[0]]=x; x=f[x]; }while(x!=y); while(d[0])down(d[d[0]--]); } void splay(int x,int y){ remove(x,y); while(f[x]!=y){ if(f[f[x]]!=y) if(son(f[x])==son(x))rotate(f[x]);else rotate(x); rotate(x); } if(!y)root=x; } void suoga(int x){ down(x);x=t[x][1]; while(x){ down(x); if(t[x][0])x=t[x][0];else break; } splay(x,0); } void dele(int x){ f[t[x][0]]=f[x]; t[f[x]][0]=t[x][0]; update(f[x]); } int build(int l,int r,int fa){ int mid=(l+r)/2; if(l>r)return 0; f[mid]=fa;size[mid]=r-l+1; if(l==r)return l; t[mid][0]=build(l,mid-1,mid); t[mid][1]=build(mid+1,r,mid); return mid; } int main(){ scanf("%d",&n); fo(i,1,n){ scanf("%d",&a[i]); b[i].a=a[i];b[i].b=i; } sort(b+1,b+1+n,cmp); build(1,n+1,0); fo(i,1,n){ splay(b[i].b,0);back(t[root][0]); printf("%d",size[t[root][0]]+i); if(i!=n)printf(" "); suoga(root); dele(t[root][0]); } }