您的位置:首页 > 其它

HDU 1890 Robotic Sort(splay)

2016-03-19 11:45 471 查看
【题目链接】

http://acm.hdu.edu.cn/showproblem.php?pid=1890

【题意】

给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i的所在位置。相等的两个数排序后相对位置不变。

【思路】

由于相对位置不变,所以可以根据数值与位置重编号。

依旧使用直接定位从上到下旋转至根的splay写法。每次将i结点旋转至根,则答案为左儿子大小+i,然后将i删掉合并左右儿子。

需要注意合并时判断左右儿子是否为空,以及各种pushdown下传标记。

【代码】

#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std;

typedef long long ll;
const int N = 5e5+10;

ll read() {
char c=getchar();
ll f=1,x=0;
while(!isdigit(c)) {
if(c=='-') f=-1; c=getchar();
}
while(isdigit(c))
x=x*10+c-'0',c=getchar();
return x*f;
}

struct Node *null;
struct Node {
int v,s,rev;
Node *ch[2],*fa;
void init(int x) {
v=x;
s=rev=0;
ch[0]=ch[1]=fa=null;
}
void pushdown() {
if(rev) {
swap(ch[0],ch[1]);
ch[0]->rev^=1; ch[1]->rev^=1;
rev=0;
}
}
void maintain() {
s=ch[0]->s+ch[1]->s+1;
}
} nodepool
,*node
;

void rot(Node* o,int d) {
Node *k=o->ch[d],*tmp=null;
o->ch[d]=k->ch[d^1];
if((tmp=k->ch[d^1])!=null) tmp->fa=o;
k->ch[d^1]=o;
if((tmp=o->fa)!=null) tmp->ch[tmp->ch[1]==o]=k;
o->fa=k; k->fa=tmp;
}
Node *st[N<<3];
void up_push(Node* u) {
int top=0;
while(u!=null)
st[++top]=u,u=u->fa;
while(top)
st[top--]->pushdown();
}
void splay(Node* o,Node* des=null) {
up_push(o);
Node *nf,*nff;
while(o!=des && (nf=o->fa)!=des) {
nff=nf->fa;
if(nff==des) rot(nf,nf->ch[1]==o),nf->maintain();
else {
int d1=nf->ch[1]==o,d2=nff->ch[1]==nf;
if(d1==d2) rot(nff,d2),rot(nf,d1);
else rot(nf,d1),rot(nff,d2);
nff->maintain(),nf->maintain();
}
}
o->maintain();
}
void reverse(Node* o) {
swap(o->ch[0],o->ch[1]);
o->ch[0]->rev^=1;
o->ch[1]->rev^=1;
}
Node* getbound(Node* o,int d) {
o->pushdown();
if(o->ch[0]==null&&o->ch[1]==null) return o;
if(o->ch[d]!=null) return getbound(o->ch[d],d);
else return o;
}
void merge(Node* u,Node* v) {
if(u->ch[1]==null) u->ch[1]=v;
else {
u=getbound(u,1);
splay(u);
u->ch[1]=v;
}
v->fa=u; u->maintain();
}

int n,a
;

Node* build(int l,int r,Node* fa) {
if(l>r) return null;
int mid=l+r>>1;
Node* o=node[a[mid]];
o->fa=fa;
o->v=a[mid];
o->ch[0]=build(l,mid-1,o);
o->ch[1]=build(mid+1,r,o);
o->maintain();
return o;
}
struct snode {
int a,rank;
bool operator < (const snode& rhs) const {
return a<rhs.a||(a==rhs.a&&rank<rhs.rank);
}
} nodes
;

int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
while(n=read(),n) {
null=new Node();
FOR(i,1,n) {
a[i]=read();
nodes[i]=(snode){a[i],i};
node[i]=&nodepool[i];
nodepool[i].init(0);
}
sort(nodes+1,nodes+n+1);
FOR(i,1,n) a[nodes[i].rank]=i;
build(1,n,null);
FOR(i,1,n-1) {
Node* o=node[i];
splay(o);
printf("%d ",o->ch[0]->s+i);
Node *lc=o->ch[0],*rc=o->ch[1];
o->ch[0]=o->ch[1]=null;
lc->fa=rc->fa=null;
if(lc!=null) {
lc->pushdown();
if(rc!=null) rc->pushdown();
reverse(lc);
merge(lc,rc);
}
}
printf("%d\n",n);
}
return 0;
}


P.S.好久之前就想切掉这道题了,但一直苦于没有正确的姿势=-=
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: