博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj1552】[Cerc2007]robotic sort Splay
阅读量:5031 次
发布时间:2019-06-12

本文共 2688 字,大约阅读时间需要 8 分钟。

题目描述

输入

输入共两行,第一行为一个整数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 
#include
#define N 100005using 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;}

 

转载于:https://www.cnblogs.com/GXZlegend/p/6289860.html

你可能感兴趣的文章
Spring整合hibernate:3、使用XML进行声明式的事务管理
查看>>
SqlServer之Convert 函数应用格式化日期(转)
查看>>
软件测试领域中的10个生存和发展技巧
查看>>
Camera前后摄像头同时预览
查看>>
HDU 1856
查看>>
课堂作业01--架构师的职责
查看>>
iOS计算富文本(NSMutableAttributedString)高度
查看>>
2017/09/15 ( 框架2)
查看>>
Centos下源码安装git
查看>>
gulp-rev-append md5版本号
查看>>
IO流之File类
查看>>
sql 基础语句
查看>>
CF717A Festival Organization(第一类斯特林数,斐波那契数列)
查看>>
oracle直接读写ms sqlserver数据库(二)配置透明网关
查看>>
控件发布:div2dropdownlist(div模拟dropdownlist控件)
查看>>
Oracle composite index column ordering
查看>>
ActiveReports 报表控件官方中文入门教程 (3)-如何选择页面报表和区域报表
查看>>
kaggle竞赛
查看>>
区块链入门教程
查看>>
域 搭建OU 组织单元
查看>>