【题目链接】

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+; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Node *null;
struct Node {
int v,s,rev;
Node *ch[],*fa;
void init(int x) {
v=x;
s=rev=;
ch[]=ch[]=fa=null;
}
void pushdown() {
if(rev) {
swap(ch[],ch[]);
ch[]->rev^=; ch[]->rev^=;
rev=;
}
}
void maintain() {
s=ch[]->s+ch[]->s+;
}
} nodepool[N],*node[N]; void rot(Node* o,int d) {
Node *k=o->ch[d],*tmp=null;
o->ch[d]=k->ch[d^];
if((tmp=k->ch[d^])!=null) tmp->fa=o;
k->ch[d^]=o;
if((tmp=o->fa)!=null) tmp->ch[tmp->ch[]==o]=k;
o->fa=k; k->fa=tmp;
}
Node *st[N<<];
void up_push(Node* u) {
int top=;
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[]==o),nf->maintain();
else {
int d1=nf->ch[]==o,d2=nff->ch[]==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[],o->ch[]);
o->ch[]->rev^=;
o->ch[]->rev^=;
}
Node* getbound(Node* o,int d) {
o->pushdown();
if(o->ch[]==null&&o->ch[]==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[]==null) u->ch[]=v;
else {
u=getbound(u,);
splay(u);
u->ch[]=v;
}
v->fa=u; u->maintain();
} int n,a[N]; Node* build(int l,int r,Node* fa) {
if(l>r) return null;
int mid=l+r>>;
Node* o=node[a[mid]];
o->fa=fa;
o->v=a[mid];
o->ch[]=build(l,mid-,o);
o->ch[]=build(mid+,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[N]; int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
while(n=read(),n) {
null=new Node();
FOR(i,,n) {
a[i]=read();
nodes[i]=(snode){a[i],i};
node[i]=&nodepool[i];
nodepool[i].init();
}
sort(nodes+,nodes+n+);
FOR(i,,n) a[nodes[i].rank]=i;
build(,n,null);
FOR(i,,n-) {
Node* o=node[i];
splay(o);
printf("%d ",o->ch[]->s+i);
Node *lc=o->ch[],*rc=o->ch[];
o->ch[]=o->ch[]=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 ;
}

P.S.好久之前就想切掉这道题了,但一直苦于没有正确的姿势=-=

HDU 1890 Robotic Sort(splay)的更多相关文章

  1. HDU 1890 Robotic Sort (splay tree)

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  2. HDU 1890:Robotic Sort(Splay)

    http://acm.hdu.edu.cn/showproblem.php?pid=1890 题意:有一个无序序列,经过不断地翻转,使得最后的序列是一个升序的序列,而且如果相同数字要使在原本序列靠前的 ...

  3. hdu 1890 Robotic SortI(splay区间旋转操作)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 题解:splay又一高级的功能,区间旋转这个是用线段树这些实现不了的,这题可以学习splay的旋 ...

  4. hdu 1890 Robotic Sort(splay 区间反转+删点)

    题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...

  5. HDU 5775 Bubble Sort(冒泡排序)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  6. HDU 1890 Robotic Sort | Splay

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Pr ...

  7. 数据结构(Splay平衡树):HDU 1890 Robotic Sort

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  8. HDU 4441 Queue Sequence(splay)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...

  9. HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Li ...

随机推荐

  1. C++:类的组合

    在类中定义的数据成员一般都是基本数据类型或服复合数据类型.但是还可以根据需要使用 其他类的对象作为正在声明的数据成员.复杂的对象还可以有比较简单的对象一某种方式组合 而成,复杂对象和组成它的简单对象之 ...

  2. linq 分类

    linq技术为我们开发人员提供了五个比较实用的数据访问类型: LinQ to Object:可以允许对内存中的类对象查询. LinQ to DataSet:可以对内存中的DataSet缓存数据,执行数 ...

  3. ubuntu 映射网络驱动器到本地

    公司办公都是在ubuntu服务器上,所以每每拷贝修改文件都要ftp之类的,实在不方便. 索性将服务器挂载到自己本地目录下. 服务器端参考其他samba安装和配置.这里只是说下本地自动挂载方法. 一.首 ...

  4. Servlet概述

    1.Servlet简介 Servlet是使用Java Servlet应用程序设计接口及相关类和方法的Java程序.它在Web服务器上或应用服务器上运行并扩展了该服务器的能力.Servlet装入Web服 ...

  5. VMware下Ubantu与Windows共享文件夹的方法

    刚刚接触linux的同学往往喜欢在windows系统下安装一个虚拟机,然后在虚拟机上进行操作,但是windows和虚拟机上的linux系统之间的文件互传往往不太方便,今天就总结一个小技巧在window ...

  6. 关于post get ajax

    今天写程序时  出现了下面问题: 前台 $.post('ajax/GetDataAjax.ashx', { 'mode': 'DEL', 'BM_ID': bm_id }, function (res ...

  7. iOS开发:在Xcode中用Pods管理第三方库

    之前写了一篇 iOS开发:在Swift中调用oc库 ,今天记录一下如何用Pods的方式来管理第三方库,包括Swift/Object-C的库. 在这之前请先查阅Guides.CocoaPods如何使用的 ...

  8. UVa 1467 (贪心+暴力) Installations

    题意: 一共有n项服务,每项服务有安装的时间s和截止时间d.对于每项任务,如果有一项超出截止时间,惩罚值为所超出时间的长度.问如何安装才能使惩罚值最大的两个任务的惩罚值之和最小. 分析: 如果是求总惩 ...

  9. PhoneGap 安装体验

    npm -v #显示版本,检查npm 是否正确安装. npm install express #安装express模块 npm install -g express #加上 -g 启用global安装 ...

  10. 【转】Linux时间函数之gettimeofday()函数之使用方法

    原文网址:http://blog.csdn.net/tigerjibo/article/details/7039434 一.gettimeofday()函数的使用方法: 1.简介: 在C语言中可以使用 ...