HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
In this task, you are to write software for a robot that handles samples in such a laboratory. Imagine there are material samples lined up on a running belt. The samples have different heights, which may cause troubles to the next processing unit. To eliminate such troubles, we need to sort the samples by their height into the ascending order.
Reordering is done by a mechanical robot arm, which is able to pick up any number of consecutive samples and turn them round, such that their mutual order is reversed. In other words, one robot operation can reverse the order of samples on positions between A and B.
A possible way to sort the samples is to find the position of the smallest one (P1) and reverse the order between positions 1 and P1, which causes the smallest sample to become first. Then we find the second one on position P and reverse the order between 2 and P2. Then the third sample is located etc.
The picture shows a simple example of 6 samples. The smallest one is on the 4th position, therefore, the robot arm reverses the first 4 samples. The second smallest sample is the last one, so the next robot operation will reverse the order of five samples on positions 2–6. The third step will be to reverse the samples 3–4, etc.
Your task is to find the correct sequence of reversal operations that will sort the samples using the above algorithm. If there are more samples with the same height, their mutual order must be preserved: the one that was given first in the initial order must be placed before the others in the final order too.
The last scenario is followed by a line containing zero.
Each Pi must be an integer (1 ≤ Pi ≤ N ) giving the position of the i-th sample just before the i-th reversal operation.
Note that if a sample is already on its correct position Pi , you should output the number Pi anyway, indicating that the “interval between Pi and Pi ” (a single sample) should be reversed.
题意:
给出一个n,给出n个样品的高度,
给出一种根据高度排序的算法,其第 i 次操作:找到第 i 小的那个数的位置为Pi,将整个区间[i,Pi]反转,这样一来第 i 小的数就在位置 i 上;从 i 等于 1 到 n 循环这样的操作。
现在要求你给出每次操作的Pi。
题解:
伸展树1~n建树,把每个节点key值等于节点的编号(即key[x] = x),同时使得中序遍历伸展树得到的序列为1~n,
以题目中两个样例为例,建成的树应为如下图:
(注意,图中节点内的数字,既是节点编号,也是key值,即key[3] = 3,key[1] = 1,key[5] = 5……)
我们此时的伸展树维护的是n个样品的编号(编号为1~n);
将n个样品按输入顺序编号,再按照first高度second编号进行升序排序,那么新的顺序,就是题目中所描述的排序算法中的每次操作的顺序,
这样,按新的顺序依次枚举n个样品,对于第 i 个样品,其编号为sample[i].id,
我们此时就要去伸展树中寻找某个节点x,其key[x] = sample[i].id;而我们要求的Pi,就是比这个节点小的节点个数加1;
根据上面反复提到的,key[x] = x,所以我们其实就是把节点x = sample[i].id伸展到根,然后求其左子树内节点个数,再加1,
同时,因为需要区间翻转,所以我们可以翻转左子树,并且删除根节点,相当于翻转了[i,Pi],
由于我们不断的删除节点,因此实际答案就应该是左子树内节点个数 + 1 + (i - 1)。
AC代码:
#include<bits/stdc++.h>
#define Key_value ch[ch[root][1]][0]
using namespace std;
const int maxn=1e5+; int n;
struct Sample
{
int h;
int id;
}sample[maxn];
bool cmp(Sample a,Sample b)
{
if(a.h==b.h) return a.id<b.id;
else return a.h<b.h;
} /******************************** splay - st ********************************/
int root,nodecnt;
int par[maxn],ch[maxn][];
int key[maxn],size[maxn];
bool rev[maxn];
void NewNode(int &x,int p,int k)
{
x=k;
par[x]=p;
ch[x][]=ch[x][]=;
key[x]=k;
size[x]=;
rev[x]=;
}
void Update_Rev(int x)
{
if(x==) return;
rev[x]^=1;
}
void Pushup(int x)
{
size[x]=size[ch[x][]]+size[ch[x][]]+;
}
void Pushdown(int x)
{
if(rev[x])
{
swap(ch[x][],ch[x][]);
Update_Rev(ch[x][0]);
Update_Rev(ch[x][1]);
rev[x]=;
}
}
void Rotate(int x,int type) //旋转,0为左旋zag,1为右旋zig
{
int y=par[x];
Pushdown(y); Pushdown(x); //先把y的标记向下传递,再把x的标记往下传递
ch[y][!type]=ch[x][type]; par[ch[x][type]]=y;
if(par[y]) ch[par[y]][(ch[par[y]][]==y)]=x;
par[x]=par[y];
ch[x][type]=y; par[y]=x;
Pushup(y); Pushup(x);
}
void Splay(int x,int goal)
{
Pushdown(x);
while(par[x]!=goal)
{
if(par[par[x]]==goal)
{
Pushdown(par[x]); Pushdown(x);
Rotate(x,ch[par[x]][]==x); //左孩子zig,有孩子zag
}
else
{
Pushdown(par[par[x]]); Pushdown(par[x]); Pushdown(x);
int y=par[x];
int type=(ch[par[y]][]==y); //type=0,y是右孩子;type=1,y是左孩子
if(ch[y][type]==x)
{
Rotate(x,!type);
Rotate(x,type);
}
else
{
Rotate(y,type);
Rotate(x,type);
}
}
}
if(goal==) root=x;
}
int Get_Kth(int x,int k) //得到第k个节点
{
Pushdown(x);
int t=size[ch[x][]]+;
if(t==k) return x;
if(t>k) return Get_Kth(ch[x][],k);
else return Get_Kth(ch[x][],k-t);
}
int Get_Min(int x)
{
Pushdown(x);
while(ch[x][])
{
x=ch[x][];
Pushdown(x);
}
return x;
}
int Get_Max(int x)
{
Pushdown(x);
while(ch[x][])
{
x=ch[x][];
Pushdown(x);
}
return x;
}
void Build(int &x,int l,int r,int par)
{
if(l>r) return;
int mid=(l+r)/;
NewNode(x,par,mid);
Build(ch[x][],l,mid-,x);
Build(ch[x][],mid+,r,x);
Pushup(x);
}
void Init()
{
root=nodecnt=;
ch[root][]=ch[root][]=size[root]=key[root]=par[root]=rev[root]=;
Build(root,,n,);
}
void Del()
{
if(ch[root][]== && ch[root][]==) root=;
else if(ch[root][]==)
{
par[ch[root][]]=;
root=ch[root][];
}
else if(ch[root][]==)
{
par[ch[root][]]=;
root=ch[root][];
}
else
{
int pre=Get_Max(ch[root][]);
int nxt=Get_Min(ch[root][]);
Splay(pre,); Splay(nxt,root);
par[Key_value]=;
Key_value=;
Pushup(ch[root][]);
Pushup(root);
}
}
/******************************** splay - ed ********************************/ int main()
{
while(scanf("%d",&n) && n!=)
{
Init();
for(int i=;i<=n;i++)
{
scanf("%d",&sample[i].h);
sample[i].id=i;
}
sort(sample+,sample+n+,cmp); for(int i=;i<n;i++)
{
Splay(sample[i].id,);
printf("%d ",i+size[ch[root][]]);
Update_Rev(ch[root][]);
Del();
}
printf("%d\n",n);
}
}
HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]的更多相关文章
- hdu 1890 Robotic Sort(splay 区间反转+删点)
题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...
- HDU1890 Robotic Sort Splay tree反转,删除
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 题目中涉及数的反转和删除操作,需要用Splay tree来实现.首先对数列排序,得到每个数在数列 ...
- HDU 1890 Robotic Sort | Splay
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) [Pr ...
- HDU 1890 Robotic Sort (splay tree)
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- 数据结构(Splay平衡树):HDU 1890 Robotic Sort
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- hdu1890 Robotic Sort (splay+区间翻转单点更新)
Problem Description Somewhere deep in the Czech Technical University buildings, there are laboratori ...
- HDU 1890 Robotic Sort(splay)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1890 [题意] 给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i ...
- hdu 1890 Robotic Sort
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 如下: #include<cstdio> #include<cstdlib&g ...
- 算法模板——splay区间反转 2
实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...
随机推荐
- GDAL------API
转载:http://gdal.org/java/org/gdal/gdal/gdal.html
- SpringMVC由浅入深day02_8json数据交互
8 json数据交互 8.1 为什么要进行json数据交互 json数据格式在接口调用中.html页面中较常用,json格式比较简单,解析还比较方便. 比如:webservice接口,传输json数据 ...
- 8 -- 深入使用Spring -- 8... Spring整合Hibernate
8.8 Spring整合Hibernate 8.8.1 Spring提供的DAO支持 8.8.2 管理Hibernate的SessionFactory 8.8.3 实现DAO组件的基类 8.8.4 传 ...
- 8 -- 深入使用Spring -- 4...1 为什么需要AOP
8.4.1 为什么需要AOP AOP专门用于处理系统中分布于各种模块(不同方法)中的交叉关注点的问题,在Java EE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓 ...
- iOS开发--libxml/HTMLparser.h file not found 解决方法 (libxml.dylib错误处理)
点击左边项目的根目录,再点击右边的Build Settings,手工输入文字:“Header search paths”,然后单击(或双击,点击弹出面板下面的“+”号进行添加)“ Header sea ...
- SaltStack 批量分发目录
这里演示如何将 salt-master 上的目录批量分发到多台 salt-minion,步骤如下: [root@localhost ~]$ cat /srv/salt/top.sls # 先定义入口配 ...
- Ansible常用模块使用
Ansible官方提供了非常多的模块,还有若干第三方模块,我们也可以自己编写模块. Ansible对远程服务器的操作实际是通过模块完成的,先将模块拷贝到远程服务器,完成操作后,然后在远程服务器上删除该 ...
- windows7内核分析之x86&x64第二章系统调用
windows7内核分析之x86&x64第二章系统调用 2.1内核与系统调用 上节讲到进入内核五种方式 其中一种就是 系统调用 syscall/sysenter或者int 2e(在 64 位环 ...
- elasticsearch基础----->elasticsearch环境的搭建
这里面我们主要是在ubuntu系统上对elasticsearch进行一个环境的搭建,记录一下这个过程中遇到的一些问题以及解决方案.我总是躲在梦与季节的深处,听花与黑夜唱尽梦魇,唱尽繁华,唱断所有记忆的 ...
- 原生js--键盘事件
键盘事件知识点: 1.如果用户按键事件足够长,在keyup事件触发之前,会触发多次keydown事件 2.通过keyCode(charCode firefox)指定按下的是哪个键,采用unicode编 ...