/*
我们要如何知道每次该旋转哪个block呢?即便我们知道该旋转哪个block,那这个block在splay中又处于哪个位置呢?
对于第一个问题,我们可以先将block排个序,这样自然就知道每次该旋转哪个block了。
对于第二个问题,我们可以在建树的过程中把每个block所在的节点的标号存下来即可。
——————————————(转自http://www.cnblogs.com/staginner/archive/2012/04/01/2427883.html)
flip要知道的是size为a,b的block所以先把此次的block旋转到根求其size
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define KeyTree (ch[ch[root][1]][0])
using namespace std;
const int maxn =300005;
struct Node {
int key;
int cur;
int id;
bool operator <(const Node & t )const {
if(key==t.key)
return id<t.id;
return key<t.key;
}
}p[maxn];
struct SplayTree {
int tot,root;
int pre[maxn];
int size[maxn];
int ch[maxn][2];
inline void chear() {
pre[0] =ch[0][0] =ch[0][1] =0;
size[0] =0;
rev[0] = 0;
root =0;
tot =0 ;
}
inline void Rotate(int x, int c) {
int y = pre[x];
push_down(y); push_down(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;
push_up(y);
}
inline void Splay(int x, int f) {// x,f都是节点标号
push_down(x);
while ( pre[x] != f ) {
int y = pre[x], z = pre[y];
push_down(z); push_down(y); push_down(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);
}
}
}
}
push_up(x);
if ( f == 0 ) root = x;//root为父亲节点为0的点
}
inline void Select(int k, int f) { //k为先序遍历第k个数,f节点编号
int x = root;
while ( 1 ) {
push_down(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 push_down(int x){
if(rev[x]){
rev[x]=false;
rev[ ch[x][0]]= !rev[ch[x][0]];
rev[ ch[x][1]]= !rev[ch[x][1]];
int tmp = ch[x][0]; ch[x][0] = ch[x][1]; ch[x][1] = tmp;
}
}
inline void push_up(int x){
size[x]= 1+ size[ch[x][0]]+size[ch[x][1]];
}
inline void NewNode(int &x ,int f,int id){
x = ++tot;
pre[x]=f;
ch[x][0]=ch[x][1]=0;
val[x]=p[id].key;
p[id].cur=x;
rev[x]=false;
size[x]=1;
}
void MakeTree(int &x ,int l,int r,int f){
if(l>r)return ;
int mid=(l+r)>>1;
NewNode(x,f,mid);
MakeTree(ch[x][0],l,mid-1,x);
MakeTree(ch[x][1],mid+1,r,x);
push_up(x);
}
inline void init(int n){
chear();
NewNode(root,0,0);//虚设两个节点
NewNode(ch[root][1],root,n+1);//虚设节点
MakeTree(KeyTree,1,n,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
inline void flip(int a,int b){
Select(a-1+1,0);
Select(b+1+1,root);
rev[KeyTree]=!rev[KeyTree];
}
int Gao(int a,int b){
Splay(b,0);
int ret=size[ch[b][0]];
flip(a,ret);
return ret;
}
int top;
int val[maxn];
int stk[maxn];
bool rev[maxn];
}spt;
int main(){
int n;
int i,j;
while(scanf("%d",&n)!=EOF && n){
for(i=1;i<=n;i++){
scanf("%d",&p[i].key);
p[i].id=i;
}
spt.init(n);
sort(p+1,p+n+1);
for(i=1;i<=n;i++){
if(i!=1)printf(" ");
printf("%d",spt.Gao(i,p[i].cur));
}
puts("");
}
return 0;
}
HDU Robotic Sort
最新推荐文章于 2017-10-18 15:10:07 发布