https://www.luogu.org/problemnew/show/P3224

考虑对每个岛维护一颗平衡树,用并查集维护连通性,启发式合并即可

这东西其实是一个大暴力,每次把节点少的平衡树合并到节点多的平衡树里

这样可以保证每个点合并一次树的大小*2,每个点最多被插入 log(n) 次,复杂度正确

我使用了简单好写的 leafy tree 作为平衡树,不喜勿喷

  1. #include <bits/stdc++.h>
  2. #define update(u) if(u -> left -> size) u -> size = u -> left -> size + u -> right -> size, u -> value = u -> right -> value
  3. #define new_Node(a, b, c, d) (&(*st[cnt++] = Node(a, b, c, d)))
  4. #define merge(a, b) new_Node(a -> size + b -> size, b -> value, a, b)
  5. #define ratio 4
  6. using namespace std;
  7. typedef unsigned long long ull;
  8. typedef long long ll;
  9. template <typename _T>
  10. inline void read(_T &f) {
  11. f = 0; _T fu = 1; char c = getchar();
  12. while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
  13. while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
  14. f *= fu;
  15. }
  16. const int N = 300000 + 10;
  17. struct Node {
  18. int size, value;
  19. Node *left, *right;
  20. Node (int a, int b, Node *c, Node *d) : size(a), value(b), left(c), right(d) {}
  21. Node () {}
  22. }*root[N], *st[N], t[N], *null;
  23. int w[N], v[N], f[N], pre[N], len;
  24. int n, m, q, cnt = 0;
  25. void maintain(Node *u) {
  26. if(u -> left -> size > u -> right -> size * ratio) u -> right = merge(u -> left -> right, u -> right), st[--cnt] = u -> left, u -> left = u -> left -> left;
  27. if(u -> right -> size > u -> left -> size * ratio) u -> left = merge(u -> left, u -> right -> left), st[--cnt] = u -> right, u -> right = u -> right -> right;
  28. }
  29. void ins(Node *u, int x) {
  30. if(u -> size == 1) u -> left = new_Node(1, min(u -> value, x), null, null), u -> right = new_Node(1, max(u -> value, x), null, null);
  31. else ins(x > u -> left -> value ? u -> right : u -> left, x);
  32. update(u); maintain(u);
  33. }
  34. int find(Node *u, int x) {
  35. if(u -> size == 1) return u -> value;
  36. return x > u -> left -> size ? find(u -> right, x - u -> left -> size) : find(u -> left, x);
  37. }
  38. void dfs(Node *u) {
  39. if(u == null) return;
  40. st[--cnt] = u;
  41. dfs(u -> left);
  42. if(u -> size == 1) w[++len] = u -> value;
  43. dfs(u -> right);
  44. }
  45. int Merge(int a, int b) {
  46. if(root[a] -> size < root[b] -> size) swap(a, b);
  47. len = 0; dfs(root[b]);
  48. for(register int i = 1; i < len; i++) {
  49. ins(root[a], w[i]);
  50. }
  51. return a;
  52. }
  53. int find(int x) {
  54. return f[x] == x ? x : f[x] = find(f[x]);
  55. }
  56. int main() {
  57. read(n); read(m);
  58. null = new Node(0, 0, 0, 0);
  59. for(register int i = 0; i <= 300000; i++) st[i] = &t[i];
  60. for(register int i = 1; i <= n; i++) root[i] = new Node(1, INT_MAX, null, null), read(v[i]), ins(root[i], v[i]), f[i] = i, pre[v[i]] = i;
  61. for(register int i = 1; i <= m; i++) {
  62. int a, b;
  63. read(a); read(b);
  64. int x = find(a), y = find(b);
  65. if(x == y) continue;
  66. int fa = Merge(x, y);
  67. f[x] = f[y] = fa;
  68. }
  69. read(q);
  70. for(register int i = 1; i <= q; i++) {
  71. char c = getchar();
  72. while(c != 'Q' && c != 'B') c = getchar();
  73. if(c == 'Q') {
  74. int a, b;
  75. read(a); read(b);
  76. int x = find(a);
  77. if(root[x] -> size - 1 < b) {
  78. printf("-1\n");
  79. continue;
  80. }
  81. printf("%d\n", pre[find(root[x], b)]);
  82. } else {
  83. int a, b;
  84. read(a); read(b);
  85. int x = find(a), y = find(b);
  86. if(x == y) continue;
  87. int fa = Merge(x, y);
  88. f[x] = f[y] = fa;
  89. }
  90. }
  91. return 0;
  92. }

luoguP3224 [HNOI2012]永无乡的更多相关文章

  1. luoguP3224 [HNOI2012]永无乡【线段树,并查集】

    洞庭青草,近中秋,更无一点风色.玉鉴琼田三万顷,着我扁舟一叶.素月分辉,明河共影,表里俱澄澈.悠然心会,妙处难与君说. 应念岭表经年,孤光自照,肝胆皆冰雪.短发萧骚襟袖冷,稳泛沧溟空阔.尽挹西江,细斟 ...

  2. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  3. bzoj 2733: [HNOI2012]永无乡 离线+主席树

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1167  Solved: 607[Submit][Status ...

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

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

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

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

  6. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

  7. 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡

    题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...

  8. bzoj2733: [HNOI2012]永无乡 启发式合并

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec   ...

  9. [HNOI2012]永无乡 线段树合并

    [HNOI2012]永无乡 LG传送门 线段树合并练手题,写这篇博客只是为了给我的这篇文章找个板子题. 并查集维护连通性,对于不在同一个连通块内的合并操作每次直接合并两颗线段树,复杂度\(O(n \l ...

随机推荐

  1. 小白之js原生轮播图

    html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  2. leetcode378

    public class Solution { public int KthSmallest(int[,] matrix, int k) { ); ); var list = new List< ...

  3. Stars(树状数组单点更新)

    Astronomers often examine star maps where stars are represented by points on a plane and each star h ...

  4. cacti启动有图无数据

    cactiEZ服务器重启后,获取不到图形的解决办法 cd /var/www/html/cli/ php -q rebuild_poller_cache.php -d myisamchk --safe- ...

  5. SQL Server 触发器触发器

    内容摘抄自http://www.cnblogs.com/hoojo/archive/2011/07/20/2111316.html,只供自己笔记使用 触发器是一种特殊类型的存储过程,它不同于之前的我们 ...

  6. hibernate 一对一(级联关系)

    hibernate 核心配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hiber ...

  7. SQL Server 2008 R2 Express 不能启动

    今天,新安装了Sql Server 2008 R2 Express,准备部署相应系统,在完成了数据库还原,系统部署以后,从浏览器里输入系统网址,出现登录页面,登录时报错,无法连上数据库.在查找原因的过 ...

  8. hrabs的数据库session的修改

    using System;using System.Data;using System.Collections;using System.Collections.Generic;using Syste ...

  9. FreeMarker 的空值处理 , 简单理解 , 不用TMD就会忘记

    NO.1 而对于FreeMarker来说,null值和不存在的变量是完全一样的 NO.2 ! 指定缺失变量的默认值 返回String NO.3 ?? 判断变量是否存在 返回boolean NO.4 $ ...

  10. c#并发编程经典实例文摘

    第1章 并发编程概述 1.1 并发编程简介 并发: 多线程(包括并行处理) 异步编程(异步操作)程序启动一个操作,而该操作将会在一段时间后完成 响应时编程(异步事件)可以没有一个实际的开始,可以在任何 ...