【bzoj1552】[Cerc2007]robotic sort
题目描述

输入
输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。
输出
输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。
样例输入
6
3 4 5 1 6 2
样例输出
4 6 4 5 6 6
题解
splay
先将原数据从小到大排序,类似于离散化,把它们的排名存入splay中。
那么第k小的数的数组下标就是k。
区间反转即可。
#include <cstdio>
#include <algorithm>
#define N 100005
using namespace std;
struct data
{
int num , pos;
}a[N];
int c[2][N] , fa[N] , tag[N] , si[N] , id[N] , root;
bool cmp(data a , data b)
{
return a.num == b.num ? a.pos < b.pos : a.num < b.num;
}
void pushup(int k)
{
si[k] = si[c[0][k]] + si[c[1][k]] + 1;
}
void pushdown(int k)
{
if(tag[k])
{
swap(c[0][c[0][k]] , c[1][c[0][k]]);
swap(c[0][c[1][k]] , c[1][c[1][k]]);
tag[c[0][k]] ^= 1;
tag[c[1][k]] ^= 1;
tag[k] = 0;
}
}
void build(int l , int r , int f)
{
if(l > r) return;
int mid = (l + r) >> 1;
build(l , mid - 1 , mid);
build(mid + 1 , r , mid);
fa[id[mid]] = id[f];
c[mid > f][id[f]] = id[mid];
pushup(id[mid]);
}
void rotate(int &k , int x)
{
int y = fa[x] , z = fa[y] , l , r;
l = (c[0][y] != x);
r = l ^ 1;
if(y == k) k = x;
else if(c[0][z] == y) c[0][z] = x;
else c[1][z] = x;
fa[x] = z;
fa[y] = x;
fa[c[r][x]] = y;
c[l][y] = c[r][x];
c[r][x] = y;
pushup(y);
pushup(x);
}
void splay(int &k , int x)
{
while(x != k)
{
int y = fa[x] , z = fa[y];
if(y != k)
{
if(c[0][y] == x ^ c[0][z] == y) rotate(k , x);
else rotate(k , y);
}
rotate(k , x);
}
}
int getrank(int x)
{
if(x == root) return si[c[0][x]] + 1;
int r = getrank(fa[x]);
pushdown(x);
if(x == c[0][fa[x]]) r -= si[c[1][x]] + 1;
else r += si[c[0][x]] + 1;
return r;
}
int find(int k , int x)
{
pushdown(k);
if(x <= si[c[0][k]]) return find(c[0][k] , x);
else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
else return k;
}
int main()
{
int n , i;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d" , &a[i].num);
a[i].pos = i;
}
sort(a + 1 , a + n + 1 , cmp);
for(i = 1 ; i <= n ; i ++ )
id[a[i].pos + 1] = i;
id[1] = n + 1;
id[n + 2] = n + 2;
build(1 , n + 2 , 0);
root = id[(n + 3) >> 1];
for(i = 1 ; i <= n ; i ++ )
{
int ri = getrank(i) , tx , ty;
printf("%d%c" , ri - 1 , i == n ? '\n' : ' ');
tx = find(root , i);
ty = find(root , ri + 1);
splay(root , tx);
splay(c[1][root] , ty);
swap(c[0][c[0][c[1][root]]] , c[1][c[0][c[1][root]]]);
tag[c[0][c[1][root]]] ^= 1;
}
return 0;
}
【bzoj1552】[Cerc2007]robotic sort的更多相关文章
- 【BZOJ1552】[Cerc2007]robotic sort Splay
[BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...
- 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值
[bzoj1552/3506][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. ...
- 洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序
FHQ_Treap 太神辣 蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目 因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每 ...
- 【HDOJ】1890 Robotic Sort
伸展树伤不起啊,很容易wa,很容易T,很容易M. /* 1890 */ #include <iostream> #include <string> #include <m ...
- BZOJ1552/3506 [Cerc2007]robotic sort
Splay 与之前不同的是如果你仅仅是翻转左右区间的话可以在find里面做因为对他有影响的子树在做之前一定在他的上面从上到下搜索的过程可以把rever做了. 但这道题要求我们输出转换之前的,因此不能保 ...
- [BZOJ1552][Cerc2007]robotic sort
[BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...
- BZOJ 1552: [Cerc2007]robotic sort( splay )
kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...
- bzoj 1552: [Cerc2007]robotic sort
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1198 Solved: 457[Submit] ...
- 【LeetCode】147. Insertion Sort List 解题报告(Python)
[LeetCode]147. Insertion Sort List 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...
随机推荐
- json的学习笔记
json比较简单,所以先从json开始学起. 一 json的名称: json的全称是javascript object notation,中文名称为js 对象表示法. json的定义:json是一种轻 ...
- 简单时钟——css3
这里我们使用css3的特性制作一个简易的时钟,代码如下: <!DOCTYPE html><html> <head> <meta charset="U ...
- 学习笔记——状态模式State
状态模式,主要是用于存在大量case判断的操作执行,同时这些case依赖于对象的状态,那么就可以将大量的case判断封装为独立的类. Context: -state,当前状态对象. ChangeSta ...
- for循环与foreach
注意点: for循环时,可以对集合进行操作,但foreach循环中,对集合进行操作会报错: for 循环可以获取下标 如下代码: package com.tt;imp ...
- 求交集,差集,并集,善用java的set
当有题目有求这些结果时,使用集合数据结构还是很快的.需要考虑的是,注意map和set的区别. public static void main(String[] args) { Set<Integ ...
- JavaScript判断数组是否存在key
JS中复合数组associative array和对象是等同的,判断一个key是否存在于数组中(或对象是否包含某个属性),不能使用ary[key] == undefined,因为可能存在ary = { ...
- How to install / setup /upgrade PHP 5.5.x on Ubuntu 12.04 LTS
原文:http://www.dev-metal.com/how-to-setup-latest-version-of-php-5-5-on-ubuntu-12-04-lts/ 最近遇到了要在ubunt ...
- C/C++ strtok函数
一.头文件:#include <string.h> 二.函数原型:char * strtok (char *str, const char * delimiters); 三.参数:str, ...
- base库插件---拖动
/** * Created by Administrator on 2014/6/5 0005. Base-drag 基于Base库的拖拽插件 tags为你要拖拽的元素参数, 数组形式传入 */ $( ...
- HDU 5547 暴力
Sudoku Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Subm ...