题面

主席树启发式合并,每次连边维护并查集,集合大小,求lca所需信息,合并两个树上的主席树, 重点看代码.

#include <iostream>
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring> using namespace std; const int N = 8e4 + 1, M = 2e7 + 1; int n, m, SIZE, Ht[N], a[N], T;
int head[N], nxt[N<<1], ver[N<<1], tot; void add(int u, int v)
{ ver[++tot] = v, nxt[tot] = head[u], head[u] = tot; } int f[N][21], dep[N]; int LCA(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = 20; i >= 0; -- i) {
if (dep[f[u][i]] >= dep[v]) {
u = f[u][i];
}
}
assert(dep[u] == dep[v]);
if (u == v) return u;
for (int i = 20; i >= 0; -- i) {
if (f[u][i] != f[v][i]) {
u = f[u][i];
v = f[v][i];
}
}
assert(f[u][0] == f[v][0]);
return f[u][0];
} int sum[M], ls[M], rs[M], cnt, rt[N]; void insert(int &p, int l, int r, int val) {
p = ++cnt;
if (l == r) return;
int mid = l + r >> 1;
if (val <= mid) insert(ls[p], l, mid, val);
else insert(rs[p], mid + 1, r, val);
} void update(int last, int p, int l, int r, int val) {
assert(p);
sum[p] = sum[last] + 1;
if (l ==r) return;
int mid = l + r >> 1;
if (val <= mid) update(ls[last], ls[p], l, mid, val), rs[p] = rs[last];
else update(rs[last], rs[p], mid + 1, r, val), ls[p] = ls[last];
} int query(int last1, int last2, int p1, int p2, int l, int r, int k) {
if (l == r) return Ht[l];
int s = sum[ls[p1]] - sum[ls[last1]] + sum[ls[p2]] - sum[ls[last2]];
int mid = l + r >> 1;
if (k <= s) return query(ls[last1], ls[last2], ls[p1], ls[p2], l, mid, k);
else return query(rs[last1], rs[last2], rs[p1], rs[p2], mid + 1, r, k - s);
} bool vis[N];
void DFS(int u, int fa) {
vis[u] = 1;
update(rt[fa], rt[u], 1, SIZE, a[u]);
dep[u] = dep[fa] + 1;
f[u][0] = fa;
for (int i = 1; i <= 20; ++ i)
f[u][i] = f[ f[u][i - 1] ][i - 1]; for (int i = head[u]; i; i = nxt[i]) {
if (ver[i] != fa) DFS(ver[i], u);
}
} int fa[N], size[N];
int find(int x)
{ return x == fa[x] ? x : fa[x] = find(fa[x]); } void link(int &u, int &v) {
add(u, v); add(v, u);
int Fu = find(u), Fv = find(v);
if (size[Fu] > size[Fv]) swap(u, v), swap(Fu, Fv);
fa[Fv] = Fu; size[Fu] += size[Fv];
} int calc(int u, int v, int k) {
int lca = LCA(u, v);
return query(rt[lca], rt[f[lca][0]], rt[u], rt[v], 1, SIZE, k);
} int main() {
#ifndef ONLINE_JUDGE
freopen("P3302.in", "r", stdin);
freopen("P3302.out", "w", stdout);
#endif
int _;
scanf("%d %d %d %d", &_, &n, &m, &T);
for (int i = 1; i <= n; ++ i) scanf("%d", a + i), Ht[i] = a[i]; sort(Ht + 1, Ht + 1 + n);
SIZE = unique(Ht + 1 ,Ht + 1+ n) - Ht - 1;
for (int i = 1 ;i <= n; ++ i) a[i] = lower_bound(Ht + 1, Ht + 1 + SIZE, a[i]) - Ht; for (int i = 1; i <= n; ++ i) fa[i] = i, size[i] = 1, insert(rt[i], 1, SIZE, a[i]); for (int i = 1; i <= m; ++ i) {
int u, v;
scanf("%d %d", &u, &v);
link(u, v);
} for (int i = 1; i <= n; ++ i)
if (!vis[find(i)]) DFS(find(i), 0); int ans = 0;
char op[4];
while (T --) {
scanf("%s", op);
if (op[0] == 'Q') {
int x, y, k; scanf("%d%d%d", &x, &y, &k); x ^= ans, y ^= ans, k ^= ans; printf("%d\n", ans = calc(x, y, k));
} else {
int x, y; scanf("%d%d", &x, &y); x ^= ans, y ^= ans; link(x, y); DFS(x, y);
}
}
}

SDOI2013森林的更多相关文章

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

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

  2. luoguP3302 [SDOI2013]森林 主席树 启发式合并

    题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...

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

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

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

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

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

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

  6. 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并

    [BZOJ3123][Sdoi2013]森林 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整 ...

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

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

  8. 3123: [Sdoi2013]森林

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

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

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

  10. AC日记——[Sdoi2013]森林 bzoj 3123

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

随机推荐

  1. Feign Form表单POST提交

    Form表单的POST提交,调用该类接口最长用的方式就是HttpClient,如果使用Feign,如何实现呢? 首先,看下Http中已Form的形式做Post提交的定义: -------------- ...

  2. JavaScript自己整理的基础-01

    1.JavaScript 简介: JavaScript是互联网上最流行的脚本语言,所有现代的HTML都使用JavaScript.既然是脚本语言,那么它的特点就有一下三种: (1)弱类型: (2)解释型 ...

  3. 第二章:RESTful API

    学习内容 使用Spring MVC编写Restful API 使用Spring MVC处理其他web应用常见的需求和场景 如何处理静态资源和异常,如何使用Spring MVC的拦截器,文件的上传下载, ...

  4. 18年selenium3+python3+unittest自动化测试教程(上)

    第一章 自动化测试课程介绍和课程大纲 1.自动化测试课程介绍 简介:讲解什么是自动化测试和课程大纲讲解,课程需要的基础和学后的水平 python3.7+selenium3 pycharm 第二章自动化 ...

  5. 配置JAVA_HOME踩得坑 。。

    配置JAVA_HOME 的时候这里不能有空格哦 ,还以为什么呢...

  6. rest_framework --- APIView

    一.什么是rest_framework 它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架. 安装方式有很多种,可以通过pip,或者在pycharm中安装也可以 二.APIVie ...

  7. 大学C++程序设计教程期末复习重点

    第一章 1.cin与count的应用<iostream> 例: cin>>a; cout<<"hello"<<endl; cout& ...

  8. rhel7-Samba服务搭建

    服务检查: [root@localhost ~]# systemctl status smb.service● smb.service - Samba SMB Daemon   Loaded: loa ...

  9. 【cisco下针对冗余链路故障备份的处理措施】

    对于中小型的网络中,为了流量的分担,可制定负载均衡方案,但往往带来的是链路的冗余.导致多条物理线路不能够最大的发挥其作用:冗余链路随可避免环路,但在实际的网络中还是存在一些需要完善的地方: 假设有一组 ...

  10. [转]不让iTunes备份到c盘

    很多人现在的C盘都是空间不大的SSD硬盘,ITUNES备份老是占越来越大的空间,不如动手把它改成其它盘好了.下面7个步骤教你转移备份. 1.需要一个小工具:Juction.exe,如果你已经是WIN7 ...