题目描述

小Z有一片森林,含有N个节点,每个节点上都有一个非负整数作为权值。初始的时候,森林中有M条边。

小Z希望执行T个操作,操作有两类:

  1. Q x y k查询点x到点y路径上所有的权值中,第k小的权值是多少。此操作保证点x和点y连通,同时这两个节点的路径上至少有k个点。
  2. L x y在点x和点y之间连接一条边。保证完成此操作后,仍然是一片森林。

为了体现程序的在线性,我们把输入数据进行了加密。设lastans为程序上一次输出的结果,初始的时候lastans为0。

  • 对于一个输入的操作Q x y k,其真实操作为Q x^lastans y^lastans k^lastans
  • 对于一个输入的操作L x y,其真实操作为L x^lastans y^lastans。其中^运算符表示异或,等价于pascal中的xor运算符。

请写一个程序來帮助小Z完成这些操作。

对于所有的数据,n,m,T<= 8*10^48∗104 .

输入输出格式

输入格式:

第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1<=testcase<=20。

第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。

第三行包含N个非负整数表示 N个节点上的权值。

接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边。

接下来 T行,每行描述一个操作,格式为”Q x y k“或者”L x y “,其含义见题目描述部分。

输出格式:

对于每一个第一类操作,输出一个非负整数表示答案。

输入输出样例

输入样例#1: 复制

  1. 1
  2. 8 4 8
  3. 1 1 2 2 3 3 4 4
  4. 4 7
  5. 1 8
  6. 2 4
  7. 2 1
  8. Q 8 7 3 Q 3 5 1
  9. Q 10 0 0
  10. L 5 4
  11. L 3 2 L 0 7
  12. Q 9 2 5 Q 6 1 6
输出样例#1: 复制

  1. 2
  2. 2
  3. 1
  4. 4
  5. 2

说明

对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。
这些权值中,第三小的为 2,输出 2,lastans变为2。

对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。
这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。

代码

显然树上第k大直接主席树

如果连边的话,我们重构小的那一棵,连到另一棵上。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #define N 80011
  6. #define M 10000000
  7.  
  8. using namespace std;
  9.  
  10. int n, m, T, cnt, tot, test, last;
  11. int head[N], to[N << 2], nex[N << 2], val[N], ntr[N], deep[N], f[N][21], root[N], sum[M], ls[M], rs[M], fa[N], size[N];
  12. bool vis[N];
  13.  
  14. inline int read()
  15. {
  16. int x = 0, f = 1;
  17. char ch = getchar();
  18. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
  19. for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
  20. return x * f;
  21. }
  22.  
  23. inline void add(int x, int y)
  24. {
  25. to[cnt] = y;
  26. nex[cnt] = head[x];
  27. head[x] = cnt++;
  28. }
  29.  
  30. inline int find(int x)
  31. {
  32. return x == fa[x] ? x : fa[x] = find(fa[x]);
  33. }
  34.  
  35. inline void Union(int x, int y)
  36. {
  37. int fx = find(x), fy = find(y);
  38. if(fx != fy) fa[fx] = fy, size[fy] += size[fx];
  39. }
  40.  
  41. inline int query(int a, int b, int c, int d, int l, int r, int x)
  42. {
  43. if(l == r) return l;
  44. int mid = (l + r) >> 1;
  45. if(sum[ls[a]] + sum[ls[b]] - sum[ls[c]] - sum[ls[d]] >= x) return query(ls[a], ls[b], ls[c], ls[d], l, mid, x);
  46. else return query(rs[a], rs[b], rs[c], rs[d], mid + 1, r, x - (sum[ls[a]] + sum[ls[b]] - sum[ls[c]] - sum[ls[d]]));
  47. }
  48.  
  49. inline void insert(int &now, int last, int l, int r, int x)
  50. {
  51. now = ++tot;
  52. ls[now] = ls[last];
  53. rs[now] = rs[last];
  54. sum[now] = sum[last] + 1;
  55. if(l == r) return;
  56. int mid = (l + r) >> 1;
  57. if(x <= mid) insert(ls[now], ls[last], l, mid, x);
  58. else insert(rs[now], rs[last], mid + 1, r, x);
  59. }
  60.  
  61. inline void dfs(int u)
  62. {
  63. int i, v;
  64. vis[u] = 1;
  65. deep[u] = deep[f[u][0]] + 1;
  66. insert(root[u], root[f[u][0]], 1, m, val[u]);
  67. for(i = 0; f[u][i]; i++) f[u][i + 1] = f[f[u][i]][i];
  68. for(; i <= 20; i++) f[u][i] = 0;
  69. for(i = head[u]; ~i; i = nex[i])
  70. {
  71. v = to[i];
  72. if(!vis[v])
  73. {
  74. f[v][0] = u;
  75. dfs(v);
  76. }
  77. }
  78. vis[u] = 0;
  79. }
  80.  
  81. inline int lca(int x, int y)
  82. {
  83. int i;
  84. if(deep[x] < deep[y]) swap(x, y);
  85. for(i = 20; i >= 0; i--)
  86. if(deep[f[x][i]] >= deep[y]) x = f[x][i];
  87. if(x == y) return x;
  88. for(i = 20; i >= 0; i--)
  89. if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
  90. return f[x][0];
  91. }
  92.  
  93. int main()
  94. {
  95. char s[10];
  96. int i, x, y, k, fx, fy;
  97. test = read();
  98. n = read();
  99. m = read();
  100. T = read();
  101. memset(head, -1, sizeof(head));
  102. for(i = 1; i <= n; i++)
  103. {
  104. fa[i] = i, size[i] = 1;
  105. val[i] = ntr[i] = read();
  106. }
  107. for(i = 1; i <= m; i++)
  108. {
  109. x = read();
  110. y = read();
  111. add(x, y);
  112. add(y, x);
  113. Union(x, y);
  114. }
  115. sort(ntr + 1, ntr + n + 1);
  116. m = unique(ntr + 1, ntr + n + 1) - ntr - 1;
  117. for(i = 1; i <= n; i++) val[i] = lower_bound(ntr + 1, ntr + m + 1, val[i]) - ntr;
  118. for(i = 1; i <= n; i++)
  119. if(!deep[i]) dfs(i);
  120. while(T--)
  121. {
  122. scanf("%s", s);
  123. x = read() ^ last;
  124. y = read() ^ last;
  125. if(s[0] == 'Q')
  126. {
  127. k = read() ^ last;
  128. printf("%d\n", last = ntr[query(root[x], root[y], root[lca(x, y)], root[f[lca(x, y)][0]], 1, m, k)]);
  129. }
  130. else
  131. {
  132. fx = find(x), fy = find(y);
  133. if(size[fx] > size[fy]) swap(x, y);
  134. Union(x, y);
  135. f[x][0] = y;
  136. dfs(x);
  137. add(x, y);
  138. add(y, x);
  139. }
  140. }
  141. return 0;
  142. }

洛谷 P3302 [SDOI2013]森林 Lebal:主席树 + 启发式合并 + LCA的更多相关文章

  1. P3302 [SDOI2013]森林(主席树+启发式合并)

    P3302 [SDOI2013]森林 主席树+启发式合并 (我以前的主席树板子是错的.......坑了我老久TAT) 第k小问题显然是主席树. 我们对每个点维护一棵包含其子树所有节点的主席树 询问(x ...

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

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

  3. [luoguP3302] [SDOI2013]森林(主席树 + 启发式合并 + lca)

    传送门 显然树上第k大直接主席树 如果连边的话,我们重构小的那一棵,连到另一棵上. 说起来简单,调了我一晚上. 总的来说3个错误: 1.离散化写错位置写到了后面 2."="写成了& ...

  4. BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并

    BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20 ...

  5. BZOJ2123 [Sdoi2013]森林 【主席树 + 启发式合并】

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

  6. bzoj3123 [Sdoi2013]森林 树上主席树+启发式合并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3123 题解 如果是静态的查询操作,那么就是直接树上主席树的板子. 但是我们现在有了一个连接两棵 ...

  7. 洛谷 P3302 [SDOI2013]森林 解题报告

    P3302 [SDOI2013]森林 题目描述 小\(Z\)有一片森林,含有\(N\)个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有\(M\)条边. 小Z希望执行\(T\)个操作,操 ...

  8. [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)

    传送门 突然发现好像没有那么难……https://blog.csdn.net/stone41123/article/details/78167288 首先有两个操作,一个查询,一个连接 查询的话,直接 ...

  9. 洛谷 P3302 [SDOI2013]森林

    ->题目链接 题解: #include<queue> #include<cstdio> #include<cstring> #include<iostr ...

随机推荐

  1. Ajax编程(HTTP请求与响应及API)详解

    AJAX编程 即 Asynchronous [e'sɪŋkrənəs] Javascript And XML, AJAX 不是一门的新的语言,而是对现有技术的综合利用. 本质是在HTTP协议的基础上以 ...

  2. hdu 5981 Guess the number

    Guess the number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 160000/160000 K (Java/Other ...

  3. nyoj-5-kmp裸题

    题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=5 kmp统计匹配串出现次数,贼尴尬好久没做字符串题目,一开始求得是文本串的next ...

  4. Device Drivers Should Not Do Power Management

    有人对现有的电源管理提出了意见,认为驱动程序不应该做电源管理,paper地址在这里: http://www.ruf.rice.edu/~mobile/publications/xu2014apsys. ...

  5. jQUery 样式操作

    一.css样式操作的方法: 1..css("样式"):获得样式值,比如$("input").css("color")  获得input中字体 ...

  6. linux命令三

    作业一:1) 将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) [root@bogon test]# cat /etc/passwd /etc/group > /1. ...

  7. Java Thread类的yield()和join()的区别和用法

    yield: 解释它之前,先简述下,多线程的执行流程:多个线程并发请求执行时,由cpu决定优先执行哪一个,即使通过thread.setPriority(),设置了 线程的优先级,也不一定就是每次都先执 ...

  8. PhotoPicker 从头到脚

    1. 简介 PhotoPicker, 是一款开源的图片选择器.效果上和微信相似. 2. 使用方法 2.1 添加依赖 dependencies { compile 'me.iwf.photopicker ...

  9. How your script code be coverted into arm code and running on ios.

    Your script code is compiled into DLLs (assemblies) by the editor. When you build for iOS, these ass ...

  10. 跟我学Delphi Xe4 开发 IOS 一 , 重读Delphi Xe4 自带文档.

    安装了 Delphi Xe4 之后打开这个地址就是完整的官方的文档了. 虽然不是立刻能解决你的问题. 但也是必须要看一遍的. 最基础的都在这里了. ms-help://embarcadero.rs_x ...