2733: [HNOI2012]永无乡

Time Limit: 10 Sec  Memory Limit: 128 MB

Submit: 4190  Solved: 2226

[Submit][Status][Discuss]

Description

永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛
y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。

Input

输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q,
表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000 

 

对于 100%的数据 n≤100000,m≤n,q≤300000

Output

对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。

Sample Input

5 1


4 3 2 5 1

1 2

7

Q 3 2

Q 2 1

B 2 3

B 1 5

Q 2 1

Q 2 4

Q 2 3

Sample Output

-1

2

5

1

2

题解

这道题需要我们合并各个联通块并询问第k大
询问第k大可以用splay实现,但如何合并呢?
将两棵中较小的那一棵的节点全部取出来插入另一颗

这么暴力不会超时么?
我们最多合并n - 1次,每次尽量将相同大小的联通块合并,总共最多插入(n / 2) * logn次
所以总的复杂度O(nlog^2n)
【打个splay都打错调了半天= =】

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define REP(i,n) for (int i = 1; i <= (n); i++)
  6. #define isr(u) (e[e[u].f].ch[1] == u)
  7. #define sizl(u) (e[e[u].ch[0]].siz)
  8. using namespace std;
  9. const int maxn = 100005,maxm = 100005,INF = 1000000000;
  10. inline int read(){
  11. int out = 0,flag = 1;char c = getchar();
  12. while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
  13. while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
  14. return out * flag;
  15. }
  16. int rt = 0,pre[maxn],n,m,q;
  17. struct node{int v,f,ch[2],siz;}e[maxn];
  18. int find(int u) {return u == pre[u] ? u : pre[u] = find(pre[u]);}
  19. inline void pu_p(int u){e[u].siz = e[e[u].ch[0]].siz + 1 + e[e[u].ch[1]].siz;}
  20. inline void spin(int u){
  21. int s = isr(u),fa = e[u].f;
  22. e[u].f = e[fa].f;
  23. if (e[fa].f) e[e[fa].f].ch[isr(fa)] = u;
  24. e[fa].ch[s] = e[u].ch[s ^ 1];
  25. if (e[u].ch[s ^ 1]) e[e[u].ch[s ^ 1]].f = fa;
  26. e[fa].f = u;
  27. e[u].ch[s ^ 1] = fa;
  28. pu_p(fa); pu_p(u);
  29. }
  30. inline void splay(int u){
  31. while (e[u].f){
  32. if (!e[e[u].f].f) spin(u);
  33. else if (isr(u) ^ isr(e[u].f)) spin(u),spin(u);
  34. else spin(e[u].f),spin(u);
  35. }
  36. rt = u;
  37. }
  38. inline void insert(int p){
  39. int u = rt,f = 0,v = e[p].v;
  40. while(u) f = u,u = v < e[u].v ? e[u].ch[0] : e[u].ch[1];
  41. e[f].ch[v > e[f].v] = p; e[p].f = f;
  42. splay(p);
  43. }
  44. inline int Kth(int u,int k){
  45. splay(u); int Lsiz = 0;
  46. while (u){
  47. int t = Lsiz + sizl(u);
  48. if (k <= t) u = e[u].ch[0];
  49. else if (k == t + 1) return u;
  50. else Lsiz = t + 1,u = e[u].ch[1];
  51. }
  52. return -1;
  53. }
  54. inline void order(int u){
  55. int l = e[u].ch[0],r = e[u].ch[1];
  56. e[u].siz = 1; e[u].ch[0] = e[u].ch[1] = e[u].f = 0;
  57. if (l) order(l);
  58. insert(u);
  59. if (r) order(r);
  60. }
  61. inline void Merge(int u,int v){
  62. if (u == v) return;
  63. pre[v] = u;
  64. splay(v); splay(u);
  65. if (e[u].siz < e[v].siz) swap(u,v);
  66. rt = u;
  67. order(v);
  68. }
  69. int main()
  70. {
  71. int fa,fb,x,k;
  72. char c;
  73. n = read(); m = read();
  74. REP(i,n) e[i].v = read(),e[i].siz = 1,pre[i] = i,e[i].ch[0] = e[i].ch[1] = e[i].f = 0;
  75. REP(i,m) fa = find(read()),fb = find(read()),Merge(fa,fb);
  76. q = read();
  77. REP(i,q){
  78. c = getchar();
  79. while (c != 'B' && c != 'Q') c = getchar();
  80. if (c == 'B'){
  81. fa = find(read()); fb = find(read());
  82. Merge(fa,fb);
  83. }
  84. else { x = find(read()); k = read(); printf("%d\n",Kth(x,k));}
  85. }
  86. return 0;
  87. }


BZOJ2733 永无乡 【splay启发式合并】的更多相关文章

  1. 【BZOJ-2733】永无乡 Splay+启发式合并

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2048  Solved: 1078[Submit][Statu ...

  2. [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

    Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...

  3. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  4. 【洛谷3224/BZOJ2733】[HNOI2012]永无乡 (Splay启发式合并)

    题目: 洛谷3224 分析: 这题一看\(n\leq100000\)的范围就知道可以暴力地用\(O(nlogn)\)数据结构乱搞啊-- 每个联通块建一棵Splay树,查询就是Splay查询第k大的模板 ...

  5. 【BZOJ 2733】【HNOI 2012】永无乡 Splay启发式合并

    启发式合并而已啦,, 调试时发现的错误点:insert后没有splay,把要拆开的树的点插入另一个树时没有把ch[2]和fa设为null,找第k大时没有先减k,,, 都是常犯的错误,比赛时再这么粗心就 ...

  6. 洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)

    题目链接 查找排名为k的数用平衡树 合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间 并查集维护连通关系即可 O(nlogn*insert t ...

  7. 【bzoj2733】[HNOI2012]永无乡 Treap启发式合并

    题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...

  8. BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

    不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...

  9. bzoj2733 永无乡 splay树的启发式合并

    https://vjudge.net/problem/HYSBZ-2733 给一些带权点,有些点是互相连通的, 然后给出2种操作,在两点间加一条边,或者询问一个点所在的连通块内的第k小值的编号 并查集 ...

  10. 【BZOJ2733】[HNOI2012] 永无乡(启发式合并Splay)

    点此看题面 大致题意: 给你一张图,其中每个点有一个权值,有两种操作:在两点之间连一条边,询问一个点所在联通块第\(k\)小的权值. 平衡树 看到第\(k\)小,应该不难想到平衡树. 为了练习\(Sp ...

随机推荐

  1. appium+python自动化☞appium python api大全

    整理了一些常用的appium python api,供学习使用...

  2. JVM自动内存管理机制--读这篇就GO了

    之前看过JVM的相关知识,当时没有留下任何学习成果物,有些遗憾.这次重新复习了下,并通过博客来做下笔记(只能记录一部分,因为写博客真的很花时间),也给其他同行一些知识分享. Java自动内存管理机制包 ...

  3. Quartz学习--三 Hello Jdbc Quartz! 和 demo 结尾

    四. Hello JDBC Quartz! JDBC方式: 就是说通过数据库的jdbc链接来进行quartz的一个配置 Quartz支持了很好的支持 demo用例 使用mysql作为例子进行演示 相比 ...

  4. Dubbo使用心得2

  5. win7重装系统后设置Python2.7环境

    起因 台式机的主板莫名出现问题,显示器画面卡顿不能动,鼠标键盘无反应,在这种情况下只好按住电源键断电.下面重启后,显示器无画面,猜测开机后没有进BIOS.然后就拆机箱,拔下电源线后撬起主板电池几秒再放 ...

  6. ASP.NET MVC - 启动创建项目,未能加载错误

    VS2012以常规方式创建一ASP.NET MVC internet 项目.创建后F5启动项目,遇一错误: 未能加载文件或程序集“MySql.Web.v20, Version=6.9.4.0, Cul ...

  7. 5个最优秀的微信小程序UI组件库

    开发微信小程序的过程中,选择一款好用的组件库,可以达到事半功倍的效果.自从微信小程序面世以来,不断有一些开源组件库出来,下面5款就是排名比较靠前,用户使用量与关注度比较高的小程序UI组件库.还没用到它 ...

  8. Python3 解压序列

    一 普遍情况: x,y,z = 1,2,3 print("x:",x) # x:1 print("y:",y) # y:2 print("z:&quo ...

  9. 《linux内核分析》 第二周

    20135130 王川东 计算机三个“法宝”:存储程序计算机.函数调用堆栈和中断机制 深入理解函数调用堆栈: 堆栈是C语言运行时必须的一个记录调用路径和参数的空间: 作用包括: 函数调用框架: 保存参 ...

  10. java 中的 i=i++

    记得大学刚开始学C语言时,老师就说:自增有两种形式,分别是i++和++i,i++表示的是先赋值后加1,++i是先加1后赋值,这样理解了很多年也没出现问题,直到遇到如下代码,我才怀疑我的理解是不是错了: ...