HDU 1890 Robotic Sort(splay)
【题目链接】
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)的更多相关文章
- HDU 1890 Robotic Sort (splay tree)
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- HDU 1890:Robotic Sort(Splay)
http://acm.hdu.edu.cn/showproblem.php?pid=1890 题意:有一个无序序列,经过不断地翻转,使得最后的序列是一个升序的序列,而且如果相同数字要使在原本序列靠前的 ...
- hdu 1890 Robotic SortI(splay区间旋转操作)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 题解:splay又一高级的功能,区间旋转这个是用线段树这些实现不了的,这题可以学习splay的旋 ...
- hdu 1890 Robotic Sort(splay 区间反转+删点)
题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...
- HDU 5775 Bubble Sort(冒泡排序)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- HDU 1890 Robotic Sort | Splay
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) [Pr ...
- 数据结构(Splay平衡树):HDU 1890 Robotic Sort
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- HDU 4441 Queue Sequence(splay)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...
- HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Li ...
随机推荐
- Java学习笔记之:Java封装
一.引言 在面向对象程式设计方法中,封装(英语:Encapsulation)是指,一种将抽象性函式接口的实作细节部份包装.隐藏起来的方法. 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定 ...
- Dubbo分布式服务框架入门
参考http://blog.csdn.net/u013142781/article/details/50387583 一.Dubbo概念介绍 1.1.Dubbo是什么? Dubbo是一个分布式服务框架 ...
- ossec 常用命令及目录说明
1. /var/www/html/analogi -> ossec 第三方的web界面的安装目录 [root@ossec-server ~]# cd /var/www/html/analogi/ ...
- 车牌识别LPR(一)-- 研究背景
在年尾用了几天的时间将2014年的所有工作都总结了一遍,将之前的文档综合了下. 以下是LPR系统,车牌识别的一些总结资料. 第一篇:LPR研究背景 汽车的出现改变了以往出行徒步和以马代步的时代,极大地 ...
- android sqlite支持的数据类型
Sqlite3支持的数据类型 :NULL.INTEGER.REAL.TEXT.BLOB 但实际上,sqlite3也接受如下的数据类型: smallint 16 位元的整数. interge ...
- navigationbar的一些设置记录
1.设置navigationbar背景颜色 [[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]]; PS:如果颜色不对 ...
- Android开发之单例模式
参考:http://blog.csdn.net/guolin_blog/article/details/8860649 http://www.cnblogs.com/liyiran/p/5283690 ...
- bzoj1566
好题,这道题体现了换一个角度计数的思想 a1^2+a2^2+……ak^2=(变成第1种输出序列的操作序列数目)^2+(变成第2种输出序列的操作序列数目)^2…… 脑洞大一点,这就相当于两个操作序列变成 ...
- 将多个.a库合并为一个.a库的方法
如果编译了多个架构的静态库,想将它们合并为一个静态库的时候,可以用如下方法合并: sudo lipo -create /libs/ffmpeg/2.6.3/arm64/lib/libavcodec.a ...
- [反汇编练习] 160个CrackMe之010
[反汇编练习] 160个CrackMe之010. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...