[SDOI2013]森林
主席树
离散化后
每个点储存从根到它的路径上的点权
新加边时直接用启发式合并,直接把size小的重构
询问时sum[u]+sum[v]-sum[lca]-sum[fa[lca]]来比较,在树上二分
LCA用倍增求,在启发式合并时暴力更新
连通性用并查集维护,再维护每个联通快的size
空间开大点就可以过了
# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(2e5 + 10), __(1e7 + 10);
IL ll Read(){
RG char c = getchar(); RG ll x = 0, z = 1;
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, m, len, w[_], fst[_], nxt[_], to[_], cnt, deep[_], id[_], fa[17][_], ls[__], rs[__], sz[__], rt[__], num, Fa[_], size[_];
IL void Add(RG int u, RG int v){ to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++; }
IL void Build(RG int &x, RG int l, RG int r){
x = ++num; if(l == r) return;
RG int mid = (l + r) >> 1;
Build(ls[x], l, mid); Build(rs[x], mid + 1, r);
}
IL void Modify(RG int &x, RG int l, RG int r, RG int val){
sz[++num] = sz[x]; ls[num] = ls[x]; rs[num] = rs[x];
sz[x = num]++;
if(l == r) return;
RG int mid = (l + r) >> 1;
if(val <= mid) Modify(ls[x], l, mid, val);
else Modify(rs[x], mid + 1, r, val);
}
IL int Query(RG int A, RG int B, RG int C, RG int D, RG int l, RG int r, RG int k){
if(l == r) return l;
RG int sum = sz[ls[A]] + sz[ls[B]] - sz[ls[C]] - sz[ls[D]], mid = (l + r) >> 1;
if(sum >= k) return Query(ls[A], ls[B], ls[C], ls[D], l, mid, k);
else return Query(rs[A], rs[B], rs[C], rs[D], mid + 1, r, k - sum);
}
IL void Dfs(RG int u, RG int Fa){
deep[u] = deep[Fa] + 1; fa[0][u] = Fa;
for(RG int j = 1; j <= 16; j++) fa[j][u] = fa[j - 1][fa[j - 1][u]];
rt[u] = rt[Fa]; Modify(rt[u], 1, len, id[u]);
for(RG int e = fst[u]; e != -1; e = nxt[e]) if(to[e] != Fa) Dfs(to[e], u);
}
IL int LCA(RG int x, RG int y){
if(deep[x] < deep[y]) swap(x, y);
for(RG int j = 16; j >= 0; j--) if(deep[fa[j][x]] >= deep[y]) x = fa[j][x];
if(x == y) return x;
for(RG int j = 16; j >= 0; j--) if(fa[j][x] != fa[j][y]) x = fa[j][x], y = fa[j][y];
return fa[0][x];
}
IL int Find(RG int x){ return Fa[x] == x ? x : Fa[x] = Find(Fa[x]); }
int main(RG int argc, RG char* argv[]){
Read(); n = Read(); m = Read(); RG int T = Read(), ans = 0, x, y, k; num = cnt = 0;
for(RG int i = 1; i <= n; i++) id[i] = w[i] = Read(), Fa[i] = i, size[i] = 1, fst[i] = -1;
sort(w + 1, w + n + 1); len = unique(w + 1, w + n + 1) - w - 1;
for(RG int i = 1; i <= n; i++) id[i] = lower_bound(w + 1, w + len + 1, id[i]) - w;
for(RG int i = 1, u, v; i <= m; i++){
u = Read(), v = Read(), Add(u, v), Add(v, u);
RG int fx = Find(u), fy = Find(v);
Fa[fx] = fy; size[fy] += size[fx];
}
Build(rt[0], 1, len);
for(RG int i = 1; i <= n; i++) if(!deep[i]) Dfs(i, 0);
while(T--){
RG char c; scanf(" %c", &c);
x = Read() ^ ans; y = Read() ^ ans;
if(c == 'L'){
RG int fx = Find(x), fy = Find(y);
if(size[fx] < size[fy]) swap(x, y);
Dfs(y, x);
Fa[fx] = fy; size[fy] += size[fx];
Add(x, y); Add(y, x);
}
else{
k = Read() ^ ans; RG int lca = LCA(x, y);
ans = w[Query(rt[x], rt[y], rt[lca], rt[fa[0][lca]], 1, len, k)];
printf("%d\n", ans);
}
}
return 0;
}
[SDOI2013]森林的更多相关文章
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
- luoguP3302 [SDOI2013]森林 主席树 启发式合并
题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...
- P3302 [SDOI2013]森林(主席树+启发式合并)
P3302 [SDOI2013]森林 主席树+启发式合并 (我以前的主席树板子是错的.......坑了我老久TAT) 第k小问题显然是主席树. 我们对每个点维护一棵包含其子树所有节点的主席树 询问(x ...
- [BZOJ3123][Sdoi2013]森林 主席树+启发式合并
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...
- BZOJ3123: [Sdoi2013]森林(启发式合并&主席树)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4813 Solved: 1420[Submit][Status ...
- 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并
[BZOJ3123][Sdoi2013]森林 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整 ...
- 洛谷 P3302 [SDOI2013]森林 解题报告
P3302 [SDOI2013]森林 题目描述 小\(Z\)有一片森林,含有\(N\)个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有\(M\)条边. 小Z希望执行\(T\)个操作,操 ...
- 3123: [Sdoi2013]森林
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3336 Solved: 978[Submit][Status] ...
- bzoj 3123: [Sdoi2013]森林(45分暴力)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4184 Solved: 1235[Submit][Status ...
- AC日记——[Sdoi2013]森林 bzoj 3123
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3216 Solved: 944[Submit][Status] ...
随机推荐
- Linux中的 awk查找日志中的相关记录
假设要在 api.log.201707201830 文件中,(此文件的多个字段数据以不可见字符^A(键盘上按下Ctrl+V+A)分隔),要输出第70个字段: awk -F '^A' '{print $ ...
- 图论算法-网络最大流【EK;Dinic】
图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...
- mysql数据库外部无法访问
有以下两种情况: 1.mysql未分配访问权限 格式:grant 权限 on 数据库名.表名 用户@登录主机 identified by "用户密码"; grant select, ...
- 每个前端开发者必会的 20 个 JavaScript 面试题
JavaScript 未声明变量直接使用会抛出异常:var name is not defined,如果没有处理异常,代码就停止运行了.但是,使用typeof undeclared_variable并 ...
- Date 类 02
Date类 在JDK1.0中,Date类是唯一的一个代表时间的类,但是由于Date类不便于实现国际化,所以从JDK1.1版本开始,推荐使用Calendar类进行时间和日期处理.这里简单介绍一下Date ...
- 剑指offer第二天
18.二叉树的镜像 操作给定的二叉树,将其变换为源二叉树的镜像. /** public class TreeNode { int val = 0; TreeNode left = null; Tree ...
- LeetCode第五天
leetcode 第五天 2018年1月6日 22.(566) Reshape the Matrix JAVA class Solution { public int[][] matrixReshap ...
- 基于Python的Flask的开发实战(第一节Flask安装)
1.安装python虚拟环境 easy_install virtualenv easy_install pip cd /home/admin virtualenv flask-website sour ...
- eclipse导入/编译hadoop源代码
1. 确保安装好JDK和eclipse 详细教程见: http://blog.csdn.net/kangdakangdaa/article/details/11364985 2. 安装 Subclip ...
- 初版python计算器
作业: 使用正则表达式实现计算器功能. 实现: 1.实现带括号的计算 2.实现指数.加减乘除求余等功能 先看运行结果: 请输入您的计算式: 1 - 2 * ( (60-30 +(-40.0/5) * ...