[SDOI2013]森林 (启发式合并)
/*
树上主席树能够求出链上第k大, 然后启发式合并直接重构就好了
卡常数就卡呗
反正我就暴力重构了!!
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#define ll long long
#define mmp make_pair
#define M 100010
using namespace std;
int read() {
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
int fa[M][17], sz[M], rt[M], belong[M], n, m, T, cnt, a[M], b[M], deep[M], ans;
int t[M * 17 * 17], ls[M * 17 * 17], rs[M * 17 * 17];
vector<int> to[M];
char s[M];
void modify(int l, int r, int last, int &now, int v) {
now = ++cnt;
t[now] = t[last] + 1;
ls[now] = ls[last];
rs[now] = rs[last];
if(l == r) return;
int mid = (l + r) >> 1;
if(v <= mid) modify(l, mid, ls[last], ls[now], v);
else modify(mid + 1, r, rs[last], rs[now], v);
}
void dfs(int now, int f, int zu) {
belong[now] = zu;
deep[now] = deep[f] + 1;
modify(1, n, rt[f], rt[now], a[now]);
fa[now][0] = f;
for(int i = 1; i <= 16; i++) fa[now][i] = fa[fa[now][i - 1]][i - 1];
for(int i = 0; i < to[now].size(); i++) {
int vj = to[now][i];
if(vj == f) continue;
dfs(vj, now, zu);
}
}
int lca(int a, int b) {
if(deep[a] < deep[b]) swap(a, b);
int dep = deep[a] - deep[b];
for(int i = 0; dep; i++, dep >>= 1) if(dep & 1) a = fa[a][i];
if(a == b) return a;
for(int i = 16; i >= 0; i--) {
if(fa[a][i] == fa[b][i]) continue;
a = fa[a][i], b = fa[b][i];
}
return fa[a][0];
}
int query(int l, int r, int rt1, int rt2, int rt3, int rt4, int k) {
if(l == r) return l;
int mid = (l + r) >> 1;
int v = t[ls[rt4]] + t[ls[rt3]] - t[ls[rt2]] - t[ls[rt1]];
if(k <= v) return query(l, mid, ls[rt1], ls[rt2], ls[rt3], ls[rt4], k);
else return query(mid + 1, r, rs[rt1], rs[rt2], rs[rt3], rs[rt4], k - v);
}
int main() {
read();
n = read(), m = read(), T = read();
for(int i = 1; i <= n; i++) a[i] = b[i] = read();
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
for(int i = 1; i <= m; i++) {
int vi = read(), vj = read();
to[vi].push_back(vj);
to[vj].push_back(vi);
}
for(int i = 1; i <= n; i++) {
if(!belong[i]) dfs(i, 0, i);
}
for(int i = 1; i <= n; i++) sz[belong[i]]++;
while(T--) {
scanf("%s", s + 1);
if(s[1] == 'Q') {
int vi = read() ^ ans, vj = read() ^ ans, k = read() ^ ans;
int l = lca(vi, vj);
ans = b[query(1, n, rt[l], rt[fa[l][0]], rt[vi], rt[vj], k)];
cout << ans << "\n";
} else {
int vi = read() ^ ans, vj = read() ^ ans;
if(sz[belong[vi]] > sz[belong[vj]]) swap(vi, vj);
sz[belong[vj]] += sz[belong[vi]];
sz[belong[vi]] = 0;
dfs(vi, vj, belong[vj]);
to[vi].push_back(vj);
to[vj].push_back(vi);
}
}
return 0;
}
/*
10
5 0 5
1 2 3 4 5
L 1 2
L 2 3
L 1 5
L 4 5
Q 3 4 1
*/
[SDOI2013]森林 (启发式合并)的更多相关文章
- BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树
Description 给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值, 连接两棵树中的两个点 Solution 对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出 ...
- 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. 第二行包含三个整 ...
- BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并
BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20 ...
- [bzoj3123][Sdoi2013]森林_主席树_启发式合并
森林 bzoj-3123 Sdoi-2013 题目大意:给定一片共n个点的森林,T个操作,支持:连接两个不在一棵树上的两个点:查询一棵树上路径k小值. 注释:$1\le n,T \le 8\cdot ...
随机推荐
- Android IPC机制基础
概要 多进程概念及多进程常见注意事项 IPC基础:Android序列化和Binder 跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Bi ...
- VS2013 Winform程序打包部署 InstallShield2015LimitedEdition
VS2013 Winform程序打包部署 VS2013默认是没有安装打包程序的,需要手动安装,我安装的是 InstallShield2015LimitedEdition. 1.点击解决方案,右键,选择 ...
- Spark:DataFrame批量导入Hbase的两种方式(HFile、Hive)
Spark处理后的结果数据resultDataFrame可以有多种存储介质,比较常见是存储为文件.关系型数据库,非关系行数据库. 各种方式有各自的特点,对于海量数据而言,如果想要达到实时查询的目的,使 ...
- 思科模拟器-DHCP配置
一.如图做好以下拓扑图(下图我取消显示端口号) 二.配置最下面的四台上网终端为自动获取ip 三.配置中间的二层交换机:添加vlan,同时所有端口设为access类型并将其加入vlan中,以下以swit ...
- 新闻娱乐类APP的后端核心逻辑总结
一.主要功能: 用户:登录.注册(微信账号登录.手机号登录).修改.审核 内容:发布.审核.分享.点赞.收藏及置顶热推等相关操作 评论:发布.审核.点赞及热评等相关操作 消息推送:站内信如用户修改结果 ...
- Defender 防卫者
发售年份 1980 平台 街机 开发商 Williams 类型 射击 https://www.youtube.com/watch?v=gss3lxeqCok
- tomcat配置ssl证书
1.server.xml 打开已经注释掉的代码 然后添加证书地址 <Connector SSLEnabled="true" clientAuth="want&qu ...
- [JAVA]JAVA实现多线程的三种方式
1.继承Thread类,通过start()方法调用 public class MultiThreadByExtends extends Thread { @Override public void r ...
- DevExpress gridview获取单元格坐标(转)
private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventA ...
- 时间复杂度O()与KMP算法
要得到某个结果,可以有很多种方式,算法就是为了寻找一条最快的方式. 而评判其好坏的标准就是时间复杂度. O(1): 我们把执行一次的时间复杂度定义为O(1) sum = a +b; cout < ...