森林 BZOJ 3123
题解:
第k大直接用主席树解决
合并利用启发式合并,将较小的连接到较大的树上
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf = 2e9;
const int logn = ;
const int maxn = 8e4 + ;
const int maxm = 2e5;
int t, n, m, q;
int sum[maxn * ], lc[maxn * ], rc[maxn * ];
int rt[maxn];
int tot, nex[maxm], fir[maxm], ver[maxm];
int num, cnt;
int ans;
int disp[maxn];
int si[maxn], dep[maxn], anc[maxn][logn + ];
int fat[maxn];
int val[maxn];
bool vis[maxn];
inline int Get()
{
int x;
char c;
bool o = false;
while((c = getchar()) < '' || c > '')
if(c == '-') o = true;
x = c - '';
while((c = getchar()) >= '' && c <= '')
x = x * + c - '';
return (o) ? -x : x;
}
inline void Reset()
{
for(int i = ; i <= n; ++i)
disp[i] = val[i], fat[i] = i, si[i] = ;
}
inline void Disperse()
{
sort(disp + , disp + + n);
disp[] = -inf;
for(int i = ; i <= n; ++i)
if(disp[i] != disp[i - ])
disp[++num] = disp[i];
for(int i = ; i <= n; ++i)
val[i] = lower_bound(disp + , disp + + num, val[i]) - disp;
}
inline void Ins(int x, int y)
{
nex[++tot] = fir[x], fir[x] = tot, ver[tot] = y;
}
inline int Find(int x)
{
return (fat[x] != x) ? fat[x] = Find(fat[x]) : x;
}
inline void Edge(int x, int y)
{
int a = Find(x), b = Find(y);
if(a != b) fat[a] = b, si[b] += si[a];
Ins(x, y), Ins(y, x);
}
int Add(int p, int l, int r, int v)
{
int k = ++cnt;
sum[k] = sum[p] + ;
if(l == r) return k;
int mi = l + r >> ;
if(v <= mi) lc[k] = Add(lc[p], l, mi, v), rc[k] = rc[p];
else lc[k] = lc[p], rc[k] = Add(rc[p], mi + , r, v);
return k;
}
void Build(int u, int f)
{
vis[u] = true;
dep[u] = dep[f] + ;
anc[u][] = f;
for(int i = ; i <= logn; ++i)
anc[u][i] = anc[anc[u][i - ]][i - ];
rt[u] = Add(rt[f], , num, val[u]);
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(v == f) continue;
Build(v, u);
}
}
inline void Edge()
{
for(int i = ; i <= m; ++i) Edge(Get(), Get());
}
inline void Build()
{
for(int i = ; i <= n; ++i)
if(!vis[i])
Build(i, );
}
inline void Link(int x, int y)
{
int a = Find(x), b = Find(y);
if(si[a] < si[b]) swap(x, y);
dep[y] = dep[x] + ;
Build(y, x);
Ins(x, y), Ins(y, x);
}
inline int Lca(int x, int y)
{
if(dep[x] < dep[y]) swap(x, y);
for(int i = logn; i >= ; --i)
if(dep[anc[x][i]] >= dep[y])
x = anc[x][i];
if(x == y) return x;
for(int i = logn; i >= ; --i)
if(anc[x][i] != anc[y][i])
{
x = anc[x][i];
y = anc[y][i];
}
return anc[x][];
}
inline int Query(int a, int b, int c, int d, int l, int r, int k)
{
if(l == r) return disp[l];
int res = sum[lc[a]] + sum[lc[b]] - sum[lc[c]] - sum[lc[d]];
int mi = l + r >> ;
if(res >= k) return Query(lc[a], lc[b], lc[c], lc[d], l, mi, k);
return Query(rc[a], rc[b], rc[c], rc[d], mi + , r, k - res);
}
inline void Ask()
{
while(q--)
{
char c;
while((c = getchar()) != 'L' && c != 'Q');
switch(c)
{
case 'L':
{
int x = Get() ^ ans, y = Get() ^ ans;
Link(x, y);
break;
}
case 'Q':
{
int x = Get() ^ ans, y = Get() ^ ans, k = Get() ^ ans;
int lca = Lca(x, y);
ans = Query(rt[x], rt[y], rt[lca], rt[anc[lca][]], , num, k);
printf("%d\n", ans);
break;
}
}
}
}
int main()
{
t = Get(), n = Get(), m = Get(), q = Get();
for(int i = ; i <= n; ++i) val[i] = Get();
Reset();
Disperse();
Edge();
Build();
Ask();
}
森林 BZOJ 3123的更多相关文章
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
- AC日记——[Sdoi2013]森林 bzoj 3123
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3216 Solved: 944[Submit][Status] ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
- bzoj 3123: [Sdoi2013]森林(45分暴力)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4184 Solved: 1235[Submit][Status ...
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...
- BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...
- ●BZOJ 3123 [Sdoi2013]森林
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3123 题解: 主席树,在线,启发式合并 简单版(只有询问操作):[2588: Spoj 10 ...
- BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树
Description 给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值, 连接两棵树中的两个点 Solution 对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出 ...
随机推荐
- Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理
面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问"茴香豆的茴字有哪几种写法?" 所谓代理模式,是指客户端(Cl ...
- 说说三四月的app审核中的几个坑
苹果的审核在3月异常严格,听说和换了部门领导有关(道听途说),恰逢三月公司新出了一个产品,我们的产品被苹果打回四五次,今天就在简书上把这些坑填下,也让遇到的朋友以后留意,也许是近期的最后一篇文章. 坑 ...
- spark 之主成分分析
C4∗2
- CNN眼中的世界:利用Keras解释CNN的滤波器
转载自:https://keras-cn.readthedocs.io/en/latest/legacy/blog/cnn_see_world/ 文章信息 本文地址:http://blog.keras ...
- webpack之postcss集成
项目 为了 兼容各个浏览器,需要加各种 c3前缀,如果手动的加肯定 相对比较麻烦,但是现在有webpack,gulp之类的 工具可以自动给我们加上,可以说效率上加速不少.如果 配置中 做个happyp ...
- spfa模板+讲解
zz http://blog.sina.com.cn/s/blog_6ad20aef0100mc1a.html Spfa算法 (模板源代码) 这是Bellman Ford的改进算法. 算法介绍: ...
- haproxy文件的增删改查
在构建一个程序项目之前,首先需要设计程序的框架,从总体上构建一个项目中的一个个功能,之后对每一个功能进行补充,最终实现总体的功能. 1 程序的总体框架: 首先把所有的功能设计成相应的函数,用pass来 ...
- Mac如何让调整窗口大小更简单
在使用Mac的时候,你能把鼠标的光标悬停在任何程序的边缘,当光标自动变成箭头样式后,按住鼠标左键你将能随意拖动来改变程序窗口的大小.但是,这里有个问题,我们有时候很难控制把鼠标光标移动在正确的窗口边缘 ...
- Hibernate中get()与load()的区别,以及关于ThreadLocal的使用方法
一.get方法和load方法的简易理解 (1)get()方法直接返回实体类,如果查不到数据则返回null.load()会返回一个实体代理对象(当前这个对象可以自动转化为实体对象),但当代理对象被调用时 ...
- 用jquery操作xml文件
一. xml文件\内容读取 1.读取xml文件 $.get( xmlfile.xml , function (xml){ //xml即为可以读取使用的内容,具体读取见第2点 }); 2.读取xml内容 ...