题意:给定一个序列,需要我们将这个序列最终排成单调增的序列。每次操作,你需要找到最小的值(如果有多个找最前面的那个)
将未排序的起始段到这个最小值的位置之间的区间进行翻转。对每次操作输出最小值的位置。
思路:splay。我们用splay维护未排序的序列。初始值记录在a数组中,splay的val存这个结点在a数组的位置,dir存当前为排序的序
列中最小值在当前根的左端还是右端,pos记录以当前结点为根的子树中最小值的位置。每次将最小值的后继旋转到根,统计左子树
的结点个数,然后加上之前已经排序的个数-1就是这个最小值的位置。为了方便边界的处理,我们新建两个结点root,R(root),root一定
在splay树的最左端,R(root)一定在最右端。详见代码:
// file name: hdu1890.cpp //
// author: kereo //
// create time: 2014年08月30日 星期六 12时05分17秒 //
//***********************************//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=100000+100;
const int inf=0x3fffffff;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
int n,top,cnt;
int a[MAXN],st[MAXN];
struct node
{
int val,s,flip,dir,pos; //val存在a数组的位置,dir存最小值在当前根的左端还是右端,pos记录以当前结点为根的子树中最小值的位置
node *fa,*ch[2];
}nod[MAXN],nil,*root,*null;
struct Splay
{
void init(){
top=cnt=0;
nil.s=nil.val=nil.flip=nil.dir=0; null=&nil; null->ch[0]=null->ch[1]=null;
newnode(root,null,0);
newnode(root->ch[1],root,0);
push_up(root); a[0]=inf;
build(root->ch[1]->ch[0],root->ch[1],1,n);
push_up(root->ch[1]); push_up(root);
}
void newnode(node *&x,node *f,int val){
if(top) x=&nod[st[--top]];
else x=&nod[cnt++];
x->s=1; x->val=x->pos=val; x->flip=x->dir=0; x->fa=f; x->ch[0]=x->ch[1]=null;
}
void Delete(node *x,node *f){
if(x ==null) return;
f->ch[0]=null; x->fa=null;
f->pos=f->val; f->dir=0;
int r=f->ch[1] == null ? 0 : f->ch[1]->pos;
if(a[r]<a[f->pos] || a[r] == a[f->pos] && r<f->pos)
f->pos=r,f->dir=1;
st[top++]=x-nod;
}
void push_up(node *x){
x->s=1;
if(x->ch[0]!=null) x->s+=x->ch[0]->s;
if(x->ch[1]!=null) x->s+=x->ch[1]->s;
x->pos=x->val; x->dir=0;
int l=x->ch[0] == null ? 0 : x->ch[0]->pos;
int r=x->ch[1] == null ? 0 : x->ch[1]->pos;
if(a[l]<a[x->pos] || a[l] == a[x->pos] && l<x->pos)
x->pos=l,x->dir=-1;
if(a[r]<a[x->pos] || a[r] == a[x->pos] && r<x->pos)
x->pos=r,x->dir=1;
}
void push_down(node *x){
if(x->flip){
x->flip^=1;
if(x->ch[0]!=null) x->ch[0]->flip^=1;
if(x->ch[1]!=null) x->ch[1]->flip^=1;
swap(x->ch[0],x->ch[1]);
x->dir*=-1;
}
}
void rotate(node *x,int d){
node *y=x->fa;
push_down(y); push_down(x);
y->ch[d^1]=x->ch[d];
if(x->ch[d]!=null) x->ch[d]->fa=y;
x->fa=y->fa;
if(y->fa!=null){
int d1=y->fa->ch[0] == y ? 0 : 1;
y->fa->ch[d1]=x;
}
x->ch[d]=y; y->fa=x;
push_up(y);
}
void splay(node *x,node *f){
while(x->fa!=f){
push_down(x);
node *y=x->fa;
if(y->fa == f){
int d=y->ch[0] == x ? 1 : 0;
rotate(x,d);
}
else{
int d=y->fa->ch[0] == y ? 1: 0;
if(y->ch[d] == x){
rotate(x,d^1); rotate(x,d);
}
else{
rotate(y,d); rotate(x,d);
}
}
}
push_up(x);
if(f == null) root=x;
}
node *get_prefix(node *x){ //获得前驱
node *y=x->ch[0];
push_down(x); push_down(y);
while(y->ch[1]!=null){
y=y->ch[1]; push_down(y);
}
return y;
}
node *get_suffix(node *x){ //获得后继
node *y=x->ch[1];
push_down(x); push_down(y);
while(y->ch[0]!=null){
y=y->ch[0]; push_down(y);
}
return y;
}
void build(node *&x,node *f,int l,int r){
if(l>r) return ;
int mid=(l+r)>>1;
newnode(x,f,mid);
build(x->ch[0],x,l,mid-1); build(x->ch[1],x,mid+1,r);
push_up(x);
}
void update(int m){
splay(&nod[0],null);
node *x=root;
while(x->dir){
push_down(x);
if(x->dir == -1) x=x->ch[0];
else x=x->ch[1];
}
splay(x,root);
node *p1,*p2;
p2=get_suffix(x);
splay(p2,root);
int num=root->ch[1]->ch[0]->s;
num+=m;
printf("%d",num);
x->flip=1;
splay(x,null);
p1=get_prefix(x);
p2=get_suffix(x);
splay(p1,null);
splay(p2,root);
Delete(x,p2);
}
}spt;
int main()
{
while(~scanf("%d",&n) && n){
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
spt.init();
for(int i=0;i<n;i++){
spt.update(i);
if(i<n-1)
printf(" ");
}
printf("\n");
}
return 0;
}