1552: [Cerc2007]robotic sort

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1206  Solved: 460
[Submit][Status][Discuss]

Description

Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。
第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 
注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

Sample Input

6
3 4 5 1 6 2

Sample Output

4 6 4 5 6 6

一般区间翻转用splay准没错了

数字可能重复所以要离散化,因为相同数字在前面的先翻转,所以可以直接重新标号

pos[i]记录第i小的数所在树的节点编号,每次查询第i小的物品位置只要将对应的节点翻转到根

左子树的个数+1(因为开了两个哨兵节点所以这里就是左子树的个数)就是当前序列的位置

输出答案之后翻转区间,和http://blog.csdn.net/jaihk662/article/details/75675443一模一样

注意延迟标记要在"splay"的时候从根往下放!

比如要将节点x旋到根,那么从根到x这一路全部需要更新,并且更新顺序一定是从根到x

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct Res
{int val;int id;bool operator < (const Res &b) const{if(id<b.id)return 1;return 0;}
}Res;
Res s[100005];
bool comp(Res a, Res b)
{if(a.val<b.val || a.val==b.val && a.id<b.id)return 1;return 0;
}
int n, m, root;
int fa[100005], tre[100005][2], v[100005], siz[100005], rev[100005], temp[100005], pos[100005];
void Update(int k)
{siz[k] = siz[tre[k][0]]+siz[tre[k][1]]+1;
}
void Create(int l, int r, int last)
{int mid;if(l>r)return;mid = (l+r)/2;if(l==r){fa[mid] = last;siz[mid] = 1;if(mid<last)  tre[last][0] = mid;else  tre[last][1] = mid;return;}Create(l, mid-1, mid);Create(mid+1, r, mid);fa[mid] = last;if(mid<last)  tre[last][0] = mid;else  tre[last][1] = mid;Update(mid);
}
void Lazy(int k)
{if(rev[k]){swap(tre[k][0], tre[k][1]);rev[tre[k][0]] ^= 1;rev[tre[k][1]] ^= 1;rev[k] = 0;}
}
void Rotate(int x, int &k)
{int l, r, y, z;y = fa[x], z = fa[y];if(tre[y][0]==x)  l = 0;else  l = 1;r = l^1;if(y==k)k = x;else{if(tre[z][0]==y)  tre[z][0] = x;else  tre[z][1] = x;}fa[x] = z, fa[y] = x;fa[tre[x][r]] = y;tre[y][l] = tre[x][r];tre[x][r] = y;Update(y);Update(x);
}
void Splay(int x, int &k)
{int i, y, z, cnt = 0;for(i=x;fa[i];i=fa[i])temp[++cnt] = i;for(i=cnt;i>=1;i--)Lazy(temp[i]);while(x!=k){y = fa[x], z = fa[y];if(y!=k){if((tre[y][0]==x)^(tre[z][0]==y))Rotate(x, k);elseRotate(y, k);}Rotate(x, k);}
}
int Find(int k, int rank)
{int l, r;Lazy(k);l = tre[k][0], r = tre[k][1];if(siz[l]+1==rank)return k;else if(siz[l]>=rank)return Find(l, rank);elsereturn Find(r, rank-siz[l]-1);
}
void Turn(int l, int r)
{int x, y, z;x = Find(root, l-1);y = Find(root, r+1);Splay(x, root);Splay(y, tre[x][1]);z = tre[y][0];rev[z] ^= 1;
}
int main(void)
{int n, i, ans;scanf("%d", &n);for(i=1;i<=n;i++){scanf("%d", &s[i].val);s[i].id = i;}sort(s+1, s+n+1, comp);for(i=1;i<=n;i++)s[i].val = i;sort(s+1, s+n+1);for(i=2;i<=n+1;i++){v[i] = s[i-1].val;pos[v[i]] = i;}Create(1, n+2, 0);root = (n+3)/2;for(i=1;i<=n;i++){Splay(pos[i], root);ans = siz[tre[pos[i]][0]];if(i!=1)printf(" ");printf("%d", ans);Turn(i+1, ans+1);}printf("\n");return 0;
}

bzoj 1552: [Cerc2007]robotic sort bzoj 3506: [Cqoi2014]排序机械臂(splay区间翻转)相关推荐

  1. 【splay】BZOJ 1152 3506:[cqoi2014]排序机械臂

    BZOJ 1152 && 3506:[cqoi2014]排序机械臂 Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,第二行为N个用空格隔开的正整数 ...

  2. 洛谷3165 CQOI2014 排序机械臂 splay

    题目链接 题意: 给你一个长度为nnn的序列,现在有一种对序列排序的方法:假设当前最小的前iii个已经找到了,我们找到i+1i+1i+1到nnn里面最早出现的最小值,设其出现位置为jjj,我们将区间[ ...

  3. 【BZOJ3506】[CQOI2014] 排序机械臂(Splay)

    点此看题面 大致题意: 给你\(n\)个数.第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推.求 ...

  4. [bzoj1552][Cerc2007]robotic sort[bzoj3506][Cqoi2014]排序机械臂

    非常垃圾的一道平衡树,结果被日了一天.很难受嗷嗷嗷 首先不得不说网上的题解让我这个本来就不熟悉平衡树的彩笔很难受--并不好理解. 还好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法. 题 ...

  5. P3165 [CQOI2014]排序机械臂

    传送门 就是说要维护一个数据结构资瓷区间反转和查询第\(K\)大,那么splay吧 我们可以把原数组按高度为第一关键字,下标为第二关键字排序,然后直接建出splay 这样的话每次第\(K\)大直接查询 ...

  6. BZOJ 1552/1506 [Cerc2007]robotic sort

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1552 [分析] 这题哇!又有翻转操作...每次要输出第几个?是吧... 所以又要用Spla ...

  7. splay区间翻转(bzoj 3223: Tyvj 1729 文艺平衡树)

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 4854  Solved: 2844 [Submit][S ...

  8. 【bzoj3506】【CQOI2014】排序机械臂

    Description 有n个物品,每个物品有它的高度a[i],现在我们要采用一种神奇的方法把这n个物品排好序.第x次我们找到第x矮的物品位置p[x],并且把x到p[x]中间的物品翻转.如果有多个一样 ...

  9. bzoj15523506 robotic sort

    这道题提醒了我: 1.交之前要删文件 2.v不要打成mn 3.maintain的位置 4.pushdown pushdown pushdown 1 #include<cstdio> 2 # ...

最新文章

  1. 无线路由安全功能的保证之DHCP
  2. 使用git 添加远程仓库 或者 从远程仓库克隆的两种实现
  3. 走进LWRP(Universal RP)的世界
  4. 使用PM2搭建在线vue.js开发环境(以守护进程方式热启动)
  5. 【转】刨根究底正则表达式(1):开篇
  6. 打印英文年历C语言函数,C语言打印年历
  7. css代码优化思路,CSS代码优化方法
  8. 【BZOJ 1038】[ZJOI2008]瞭望塔
  9. 几种支持动作模型格式的比较(MD2,MD5,sea3d) 【转】
  10. java php mysql数据库_PHP脚本和JAVA连接mysql数据库
  11. Spring源码之事务(二)
  12. 《Java核心技术》基于Java 17全面升级
  13. idea启动jsp项目
  14. 目前主流的数据库有哪些?
  15. iPython的安装过程
  16. 年终总结:华为|字节|腾讯|京东|网易|滴滴面经分享(斩获6个offer)
  17. 怎样低成本的实现网页在移动端的适配
  18. 支持DoH的DNS服务器,使用 Docker 自建支持 DoH、DoT 的 DNS 服务器
  19. 利用关联网络,防控信用卡“养卡套现”
  20. 被误解的tinyint(1)

热门文章

  1. python自学网站-自学python有什么网站
  2. 智能机器人语音ic丨智能玩具语音识别芯片丨机器人语音播报芯片丨AI语音提示芯片...
  3. win10语音识别的设置和开启
  4. 小米商城项目解析(完)
  5. .net5 不支持winform_.NET 5.0 RC 2 发布,正式版将在11月.NET Conf大会上发布
  6. 多行省略号不显示的问题
  7. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)
  8. ncf 推荐系统_TopN物品推荐算法评测设置回顾
  9. matlab矩阵作分钟平均,提高matlab运行速度和节省空间的心得合集(ZT)
  10. linux下redis开机自启动