森林 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$到根节点路径上权值出 ...
随机推荐
- mac上使用命令行显示隐藏文件
终端中输入命令 打开<终端> - 粘贴下面的两行命令执行 defaults write com.apple.finder AppleShowAllFiles TRUEkillall Fin ...
- Python 类变量,成员变量,静态变量,局部变量
局部 class TestClass(object): val1 = 100 def __init__(self): self.val2 = 200 def fcn(self,val = 400): ...
- 快学UIautomator之uiautomatorhelp使用
1.先下载uiautomatorhelp插件 2.把uiautomatorhelp.java包放到自己的项目中 3.项目中引入uiautomatorhelp插件 4.在项目中设置一个main方法,引入 ...
- AspNetCore容器化(Docker)部署(三) —— Docker Compose容器编排
一.前言 上一篇部署了一个最基础的helloworld应用,创建了两个容器和一个network,还算应付得过来. 如果该应用继续引入mysql.redis.job等若干服务,到时候发布一次得工作量之大 ...
- Django-C001-快速入门
此文章完成度[100%]留着以后忘记的回顾.多写多练多思考,我会努力写出有意思的demo,如果知识点有错误.误导,欢迎大家在评论处写下你的感想或者纠错. Django Django是一个开放源码的We ...
- javascript中typeof、undefined 和 null
typeof 是运算符,注意不是函数,是运算符,其作用,是考察变量究竟是什么类型.或曰,是变量是否定义或是否初始化的照妖镜.返回值是字符串. undefined 表示一个对象没有被定义或者没有被初始化 ...
- 【转】Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- h5快速制作工具-企业级. 非个人无水印
Epub360 Epub是团队引入的专业级H5应用开发工具,能够快速制作出高质量的H5运营交互页面,具有动画控制.交互设定.社交应用和数据应用的特点,其制作过程就类似于制作一个PPT,比较容易上手. ...
- IP数据包的校验和算法
1.算法思路: IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下: 在发送数据时,为了计算IP数据包的校验和.应该按如下步骤: (1)把IP数据包的校验和字段置为0: ( ...
- PAT 乙级 1019
题目 题目地址:PAT 乙级 1019 思路 本题没有考虑到小于1000的情况,当小于1000的时需要给vector的向量中推入0,直到向量中有四位数字,之后再进行排序并进行相关计算 代码 #incl ...