Description

给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值,  连接两棵树中的两个点

Solution

对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出现的次数。

查询时差分即可: $sum[x]+sum[y]-sum[lca]-sum[f[lca]]$

连边时需要启发式合并,将节点数小的接到节点数大的上去, 再遍历小的树, 并更新权值

我刚开始以为testcase是数据组数, TLE我好久,,

Code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define rd read()
  5. using namespace std;
  6.  
  7. const int N = 1e5;
  8.  
  9. int lson[N * ], rson[N * ], sum[N * ], root[N];
  10. int n, m, T, a[N], b[N], f[N][], head[N], tot, dep[N];
  11. int father[N], num[N], cnt, nd_num;
  12. int lastans, Case;
  13.  
  14. struct edge {
  15. int nxt, to;
  16. }e[N << ];
  17.  
  18. int read() {
  19. int X = , p = ; char c = getchar();
  20. for(; c > '' || c < ''; c = getchar()) if(c == '-') p = -;
  21. for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
  22. return X * p;
  23. }
  24.  
  25. void add(int u, int v) {
  26. e[++tot].to = v;
  27. e[tot].nxt = head[u];
  28. head[u] = tot;
  29. }
  30.  
  31. int find_anc(int x) {
  32. return father[x] == x ? x : father[x] = find_anc(father[x]);
  33. }
  34.  
  35. int find_lca(int x, int y) {
  36. if(dep[x] < dep[y]) swap(x, y);
  37. for(int i = ; ~i; --i) if(dep[f[x][i]] >= dep[y])
  38. x = f[x][i];
  39. if(x == y) return x;
  40. for(int i = ; ~i; --i) if(f[x][i] != f[y][i])
  41. x = f[x][i], y = f[y][i];
  42. return f[x][];
  43. }
  44.  
  45. int fd(int x) {
  46. return lower_bound(b + , b + + cnt, x) - b;
  47. }
  48.  
  49. void ins(int &o, int now, int l, int r, int pos) {
  50. o = ++nd_num;
  51. sum[o] = sum[now] + ;
  52. lson[o] = lson[now];
  53. rson[o] = rson[now];
  54. if(l == r) return;
  55. int mid = (l + r) >> ;
  56. if(pos <= mid) ins(lson[o], lson[now], l, mid, pos);
  57. else ins(rson[o], rson[now], mid + , r, pos);
  58. }
  59.  
  60. int query(int x, int y, int lca, int flca, int l, int r, int k) {
  61. if(l == r) return l;
  62. int mid = (l + r) >> , tmp;
  63. if((tmp = sum[lson[x]] + sum[lson[y]] - sum[lson[lca]] - sum[lson[flca]]) >= k) return query(lson[x], lson[y], lson[lca], lson[flca], l, mid, k);
  64. else return query(rson[x], rson[y], rson[lca], rson[flca], mid + , r, k - tmp);
  65. }
  66.  
  67. void dfs(int u) {
  68. dep[u] = dep[f[u][]] + ;
  69. for(int i = ; i <= ; ++i)
  70. f[u][i] = f[f[u][i - ]][i - ];
  71. ins(root[u], root[f[u][]], , cnt, fd(a[u]));
  72. for(int i = head[u]; i; i = e[i].nxt) {
  73. int nt = e[i].to;
  74. if(nt == f[u][]) continue;
  75. f[nt][] = u;
  76. dfs(nt);
  77. }
  78. }
  79.  
  80. int work() {
  81. lastans = ; tot = ;
  82. nd_num = ;
  83. /* memset(root, 0, sizeof(root));
  84. memset(lson, 0, sizeof(lson));
  85. memset(rson, 0, sizeof(rson));
  86. memset(head, 0, sizeof(head));
  87. memset(dep, 0, sizeof(dep));*/
  88. n = rd; m = rd; T = rd;
  89. for(int i = ; i <= n; ++i) b[i] = a[i] = rd;
  90. sort(b + , b + + n);
  91. cnt = unique(b + , b + + n) - b - ;
  92. for(int i = ; i <= n; ++i) father[i] = i, num[i] = ;
  93. for(int i = ; i <= m; ++i) {
  94. int u = rd, v = rd;
  95. int x = find_anc(u), y = find_anc(v);
  96. father[y] = x;
  97. num[x] += num[y];
  98. add(u, v); add(v, u);
  99. }
  100. for(int i = ; i <= n; ++i) if(!dep[i]) dfs(i);
  101. for(int i = ; i <= T; ++i) {
  102. char c = getchar();
  103. while(c != 'Q' && c != 'L') c = getchar();
  104. int u = rd ^ lastans, v = rd ^ lastans;
  105. if(c == 'Q') {
  106. int lca = find_lca(u, v), flca = f[lca][], k = rd ^ lastans;
  107. lastans = query(root[u], root[v], root[lca], root[flca], , cnt, k);
  108. if(lastans > cnt || lastans < ) return printf("F**k,WA\n"), ;
  109. lastans = b[lastans];
  110. printf("%d\n", lastans);
  111. }
  112. else {
  113. int x = find_anc(u), y = find_anc(v);
  114. if(num[x] < num[y]) {
  115. swap(x, y); swap(u, v);
  116. }
  117. father[y] = x;
  118. num[x] += num[y];
  119. f[v][] = u;
  120. add(v, u); add(u, v);
  121. dfs(v);
  122. }
  123. }
  124. return ;
  125. }
  126.  
  127. int main()
  128. {
  129. Case = rd;
  130. work();
  131. }

BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树的更多相关文章

  1. 【BZOJ3123】[SDOI2013] 森林(启发式合并主席树)

    点此看题面 大致题意: 给你一片森林,有两种操作:询问两点之间的第\(k\)小点权和在两棵树之间连一条边. 前置技能:树上主席树 做这道题目,我们首先要会树上主席树. 关于树上主席树,这有一道很好的例 ...

  2. bzoj 3674: 可持久化并查集加强版 (启发式合并+主席树)

    Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… ...

  3. BZOJ 2733 [HNOI2012]永无乡 - 启发式合并主席树

    Description 1: 查询一个集合内的K大值 2: 合并两个集合 Solution 启发式合并主席树板子 Code #include<cstdio> #include<cst ...

  4. BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...

  5. Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...

  6. BZOJ3123: [Sdoi2013]森林(启发式合并&主席树)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4813  Solved: 1420[Submit][Status ...

  7. bzoj 3123: [Sdoi2013]森林(45分暴力)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4184  Solved: 1235[Submit][Status ...

  8. bzoj 3123 [Sdoi2013]森林(主席树,lca,启发式合并)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  9. bzoj 3123 [Sdoi2013]森林(主席树+启发式合并+LCA)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

随机推荐

  1. oracle 连接池参数

    后来排查出数据库监听异常,发现是ORA-12519拒绝错误.后来发现是数据的连接池达到的极致. 具体解决方案如下: --首先检查process和session的使用情况,在sqlplus里面查看. S ...

  2. “2017面向对象程序设计(Java)第十三周学习总结”存在问题的反馈及本周教学安排

    “2017面向对象程序设计(Java)第十三周学习总结”存在问题的反馈及本周教学安排1. 图形界面事件处理技术是Java GUI编程核心技术,要求同学们掌握其基本原理和基本编程模型:2. 本周四理论课 ...

  3. Android Studio: Application Installation Failed

    [Android Studio: Application Installation Failed] 参考:http://stackoverflow.com/questions/32718044/and ...

  4. excel表格输入思想

    1.创建工作簿  SXSSFWorkbook wb = new SXSSFWorkbook(); //#设置单元格的垂直居中,水平居中,字体颜色 2.创建sheet  Sheet sheet = wb ...

  5. 第二篇:Jmeter功能概要

    一.jmeter工具组成部分: 1.资源生成器:用于生成测试过程中服务器,负载机的资源代码: 2.用户运行器:通常是一个脚本运行引擎,根据脚本的要求模拟指定用户行为,(lr中的controller) ...

  6. leetcode 树类型题

    树的测试框架: // leetcodeTree.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...

  7. PAT1103

    1103. Integer Factorization (30) 时间限制 1200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...

  8. Android 中Application向Activity 传递数值

    比如极光注册时获取用户的唯一标示ID需要在登录时进行传递,实现消息的指定用户推送功能 public String id; public String getId() { return id; } pu ...

  9. gridview空间使用

    1.HTML代码 <asp:GridView ID="gv_Info" runat="server" AutoGenerateColumns=" ...

  10. json 相关知识

    一:json标准格式: 标准JSON的合法符号:{(左大括号)  }(右大括号)  "(双引号)  :(冒号)  ,(逗号)  [(左中括号)  ](右中括号) JSON字符串:特殊字符可在 ...