hdu 1890 splay树
Robotic Sort
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3340 Accepted Submission(s): 1423
multimedia lab. But there are still others, serving to their original purposes.
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.
of individual samples and their initial order.
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.
3 4 5 1 6 2
4
3 3 2 1
0
4 2 4 4
/*
hdu-1890 splay树g
开始是用伸展树保存的值,然后发现如果有相同的进行了交换,然后输出的值就有问题
3 3 2 1 -> 4 2 4 4 但我的是4 2 4 3,因为我每次是去找的某个值的位置,相同值的话就可能找到较小那个值去了
假设排序后b[3] = b[4]= 3,我先处理b[3],然后b[3],b[4]交换,处理b[4]时就出现了bug,然后GG
准确说是对题意的理解上出现了,果然英语弱O__O "… 后来改用数组坐标建树,对于翻转get_kth找到其中第k个位置,然后get_next找出排序后第i大的后面那个,然后打标记即可.
至于求位置,直接把这个点旋转到根,然后计算左儿子的大小即可 hhh-2016-02-21 01:10:21
*/ #include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
typedef long double ld;
#define key_value ch[ch[root][1]][0]
const int maxn = 300010; int ch[maxn][2];
int pre[maxn],siz[maxn],num[maxn];
int rev[maxn];
int root,tot,cnt,n;
struct Node
{
int val,id;
}node[maxn]; bool cmp(Node a,Node b)
{
if(a.val != b.val) return a.val < b.val;
else return a.id < b.id;
} void push_up(int r)
{
int lson = ch[r][0],rson = ch[r][1];
siz[r] = siz[lson] + siz[rson] + 1;
} void update_rev(int r)
{
if(!r)return ;
swap(ch[r][0],ch[r][1]);
rev[r] ^= 1;
} void push_down(int r)
{
if(rev[r])
{
update_rev(ch[r][0]);
update_rev(ch[r][1]);
rev[r] = 0;
}
} void NewNode(int &r,int far,int k)
{
r = k;
pre[r] = far;
ch[r][0] = ch[r][1] = 0;
siz[r] = 1;
rev[r] = 0;
} void rotat(int x,int kind)
{
int y = pre[x];
push_down(y);
push_down(x);
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
push_up(y);
} void build(int &x,int l,int r,int far)
{
if(l > r) return ;
int mid = (l+r) >>1;
NewNode(x,far,mid);
build(ch[x][0],l,mid-1,x);
build(ch[x][1],mid+1,r,x);
push_up(x);
} void splay(int r,int goal)
{
push_down(r);
while(pre[r] != goal)
{
if(pre[pre[r]] == goal)
{
push_down(pre[r]);
push_down(r);
rotat(r,ch[pre[r]][0] == r);
}
else
{
push_down(pre[pre[r]]);
push_down(pre[r]);
push_down(r);
int y = pre[r];
int kind = ch[pre[y]][0] == y;
if(ch[y][kind] == r)
{
rotat(r,!kind);
rotat(r,kind);
}
else
{
rotat(y,kind);
rotat(r,kind);
}
}
}
push_up(r);
if(goal == 0)
root = r;
} int get_kth(int r,int k)
{
push_down(r);
int t = siz[ch[r][0]] + 1;
if(k == t)return r;
if(t > k) return get_kth(ch[r][0],k);
else return get_kth(ch[r][1],k-t);
} int get_next(int r)
{
push_down(r);
if(ch[r][1] == 0)return -1;
r = ch[r][1];
while(ch[r][0])
{
r = ch[r][0];
push_down(r);
}
return r;
} void ini(int n)
{
root = 0;
ch[root][0] = ch[root][1] = pre[root] = siz[root] = num[root] = 0 ;
NewNode(root,0,n+1);
NewNode(ch[root][1],root,n+2);
build(key_value,1,n,ch[root][1]); push_up(ch[root][1]);
push_up(root);
} int main()
{
int q,T;
int cas =1;
while(scanf("%d",&n) != EOF)
{
if(!n)
break;
for(int i=1; i <= n; i++)
{
scanf("%d",&node[i].val);
node[i].id = i;
}
sort(node+1,node+n+1,cmp);
ini(n);
for(int i = 1; i <= n; i++)
{
splay(node[i].id,0);
printf("%d",siz[ch[root][0]]);
if(i != n) printf(" ");
else printf("\n");
splay(get_kth(root,i),0);
splay(get_next(node[i].id),root);
update_rev(key_value);
}
}
return 0;
}
hdu 1890 splay树的更多相关文章
- hdu 3436 splay树+离散化*
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- [置顶] hdu 1890 伸展树区间翻转
题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...
- hdu 1890 Robotic Sort(splay 区间反转+删点)
题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...
- Splay树学习
首先给出一论文讲的很好: http://www.docin.com/p-63165342.html http://www.docin.com/p-62465596.html 然后给出模板胡浩大神的模板 ...
- hdu 5398 动态树LCT
GCD Tree Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- hdu 5002 (动态树lct)
Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- hdu 5314 动态树
Happy King Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Tot ...
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- Splay树-Codevs 1296 营业额统计
Codevs 1296 营业额统计 题目描述 Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司 ...
随机推荐
- iOS开发-OC分支结构
BOOL类型 返回值:真:YES 假:NO BOOL数据类型占一个字节的内存空间,占位符为%d. 计算机在识别时,YES就替换成1,NO就替换成0. bool是C语言中的布尔类型,返回值为true ...
- ASP.NET MVC编程——单元测试
1自动化测试基本概念 自动化测试分为:单元测试,集成测试,验收测试. 单元测试 检验被测单元的功能,被测单元一般为低级别的组件,如一个类或类方法. 单元测试要满足四个条件:自治的,可重复的,独立的,快 ...
- 集合Collection总览
前言 声明,本文使用的是JDK1.8 从今天开始正式去学习Java基础中最重要的东西--->集合 无论在开发中,在面试中这个知识点都是非常非常重要的,因此,我在此花费的时间也是很多,得参阅挺多的 ...
- JAVA_SE基础——42.final修饰符
高手勿喷~ final关键字可用于修饰类.变量和方法,它有"这是无法改变的"或者"最终"的含义,因此被final修饰的类.变量和方法将具有以下特征: 1.fin ...
- linux系统命令学习系列-用户切换命令su,sudo
先复习一下上节内容: 用户组添加groupadd 用户组修改groupmod 用户组删除groupdel 作业创建一个id为501的组group1,然后改成group2, 同时id变为502,最后删除 ...
- Python之旅_第一章Python入门
一.编程语言分类 1.机器语言:即计算机能听懂的二进制语言,0000 0001,直接操控硬件: 2.汇编语言:简写的英文标识符代替二进制语言,本质同样是直接操控硬件: 3.高级语言:用更贴近人类的语言 ...
- 关于网页设计的css+html相对定位和决定定位的理解
css中有很多定位,其中最重要的是相对定位和绝对定位: 定位很重要,不搞好,网页就会很乱,显示的完全不是自己想要的效果,自己必须掌握: 首先说一个重要的结论:绝对定位,是不占位置的,总是相对离自己最近 ...
- MySQL一些中重要命令
前言: 最近在面试的过程中,深感对MySQL一些重要命令的缺失.借着这个机会,补补这块的知识.不让自己只会增删查改,懂一些高级的东西 limit 用法 order by 用法 in 和 between ...
- Python内置函数(23)——dict
英文文档: class dict(**kwarg) class dict(mapping, **kwarg) class dict(iterable, **kwarg) Return a new di ...
- eclipse版本对应的jdk版本
Installing Eclipse is relatively easy, but does involve a few steps and software from at least two d ...