题目链接 \(Click\) \(Here\)

做法:\(Kruskal\)重构树上跑主席树

构造方法:把每条边拆出来成一个点,点权是原先的边权。每次连边的时候,连的不再是点,而是其原先点所在的联通块。

\(Kruskal\)重构树的性质:

  • 二叉树

  • 如果按最小生成树构造,则自顶到底权值递增(堆)

  • 叶节点是原先的树上节点

  • 两个在原图中可以经过权值\(<=k\)的边互相抵达的点,在最小生成树上也可以这样互相抵达,在\(Kruskal\)重构树上同理。

也就是说,假如一个点不能到比它的权值大的点,那么它能抵达的所有点就在它的子树里面。这个题目里我们从询问点跳到权值\(<=x\)中权值最大的点,其子树中的叶子节点,就是可以询问点可以通过点权\(<=x\)的点到达的所有点。

#include <bits/stdc++.h>
using namespace std; const int N = 200010;
const int M = 500010; int n, m, q, tot, INF, h[N], fa[N], val[N];
struct edge {int nxt, to;} e[N];
struct _edge {int u, v, w;}_e[M]; bool cmp (_edge lhs, _edge rhs) {
return lhs.w < rhs.w;
} int find (int x) {
return x == fa[x] ? x : fa[x] = find (fa[x]);
} int cnt, head[N]; void add_edge (int u, int v) {
e[++cnt] = (edge) {head[u], v}; head[u] = cnt;
} int rt[N];
#define mid ((l + r) >> 1) struct Segment_Node {
int sz, ls, rs;
}t[N << 5]; int modify (int _rt, int l, int r, int w) {
int p = ++rt[0];
t[p].sz = t[_rt].sz + 1;
if (l != r) {
if (w <= mid) {
t[p].ls = modify (t[_rt].ls, l, mid, w), t[p].rs = t[_rt].rs;
} else {
t[p].rs = modify (t[_rt].rs, mid + 1, r, w), t[p].ls = t[_rt].ls;
}
} else {
t[p].ls = t[p].rs = 0;
}
return p;
} int sz[N], id[N], dfn[N], deep[N], fafa[N][20], totsize[N]; int sep[N]; int num (int x) {
return lower_bound (sep + 1, sep + 1 + sep[0], x) - sep;
} void dfs (int u, int _fa) {
sz[u] = head[u] == 0;
dfn[u] = ++dfn[0];
totsize[u] = 1;
id[dfn[0]] = u;
fafa[u][0] = _fa;
deep[u] = deep[_fa] + 1;
rt[u] = modify (rt[id[dfn[u] - 1]], 1, INF, num (h[u])); //主席树维护高度
for (int i = 1; (1 << i) <= deep[u]; ++i) {
fafa[u][i] = fafa[fafa[u][i - 1]][i - 1];
}
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != _fa) {
dfs (v, u);
sz[u] += sz[v];
totsize[u] += totsize[v];
}
}
} int query (int u, int v, int l, int r, int k) {
while (l < r) {
int rch = t[t[v].rs].sz - t[t[u].rs].sz;
if (k <= rch) {
u = t[u].rs;
v = t[v].rs;
l = mid + 1;
} else {
u = t[u].ls;
v = t[v].ls;
k -= rch;
r = mid;
}
}
return l;
} int read () {
int s = 0, w = 1, ch = getchar ();
while ('9' < ch || ch < '0') {
if (ch == '-') w = -1;
ch = getchar ();
}
while ('0' <= ch && ch <= '9') {
s = (s << 1) + (s << 3) + ch - '0';
ch = getchar ();
}
return s * w;
} int main () {
memset (val, 0x3f, sizeof (val));
tot = n = read (), m = read (), q = read ();
t[0].sz = t[0].ls = t[0].rs = 0, sep[++sep[0]] = 0;
for (int i = 1; i <= n; ++i) sep[++sep[0]] = h[i] = read ();
for (int i = 1; i <= m; ++i) {
_e[i].u = read ();
_e[i].v = read ();
_e[i].w = read ();
}
sort (_e + 1, _e + 1 + m, cmp);
for (int i = 1; i <= n; ++i) fa[i] = i;
for (int i = 1; i <= m; ++i) {
int u = find (_e[i].u);
int v = find (_e[i].v);
if (u != v) {
int T = ++tot;
val[T] = _e[i].w;
fa[u] = fa[v] = fa[T] = T;
add_edge (T, u);
add_edge (T, v);
}
}
sort (sep + 1, sep + 1 + sep[0]);
INF = sep[0] = unique (sep + 1, sep + 1 + sep[0]) - sep - 1;
dfs (tot, 0);
int lastans = 0;
for (int i = 1; i <= q; ++i) {
int u = read () ^ lastans;
int x = read () ^ lastans;
int k = read () ^ lastans;
for (int j = 19; j >= 0; --j) {
if (val[fafa[u][j]] <= x) {
u = fafa[u][j];
}
}
if (sz[u] < k) {
puts ("-1");
lastans = 0;
} else {
lastans = sep[query (rt[id[dfn[u] - 1]], rt[id[dfn[u] + totsize[u] - 1]], 1, INF, k)];
printf ("%d\n", lastans);
}
}
}

Luogu P4197 Peaks的更多相关文章

  1. [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)

    题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...

  2. BZOJ 3545 / 洛谷 P4197 Peaks 解题报告

    P4197 Peaks 题目描述 在\(\text{Bytemountains}\)有\(N\)座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个 ...

  3. 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)

    传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...

  4. P4197 Peaks

    题目描述 在Bytemountains有N座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点 ...

  5. 洛谷P4197 Peaks(Kruskal重构树 主席树)

    题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...

  6. Luogu 4197 Peaks

    BZOJ 3545 带权限. 考虑离线,把所有边按照从小到大的顺序排序,把所有询问也按照从小到大的顺序排序,然后维护一个并查集和一个权值线段树,每处理一个询问就把比这个询问的$x$更小的边连上,具体来 ...

  7. P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]

    Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...

  8. 洛谷P4197 Peaks (Kruskal重构树)

    读题,只经过困难值小于等于x的路径,容易想到用Kruskal重构树:又要查询第k高的山峰,我们选择用主席树求解. 先做一棵重构树,跑一遍dfs,重构树中每一个非叶子节点对应一段区间,我们开range[ ...

  9. kruscal重构树略解

    我们先看一道题:Luogu P4197 Peaks 这道题珂以用启发式合并+主席树来做 那么强制在线呢?(bzoj 3551 [ONTAK2010]Peaks加强版) 离线做法就不行了 我们就要用一个 ...

随机推荐

  1. PLSQL 错误问题:Datebase character set (AL32UTF-8) and Client character set (ZHS16GBK) are different.

    (解决不了,网上用的是Orecal,我用的只是客户端.) 网上找到解决方法 打开注册表(ctr+R,输入regedit),根据报错提示找到注册表位置,但本机是win10 64位系统,根据以上路径找不到 ...

  2. java JSP自定义标签

    来至: http://blog.csdn.net/jiangwei0910410003/article/details/23915373 http://blog.csdn.net/jiangwei09 ...

  3. 转载:关于JESD204B转换器与FPGA匹配的设计关键点

    http://www.dzsc.com/data/2014-11-27/107442.html 随着更多的模数转换器(ADC)和数模转换器(DAC)支持最新的JESD204B串行接口标准,出现了FPG ...

  4. ES6字符串操作

    讨论字符串操作之前,我们先来了解一下Unicode 编码的由来,因为Js中的字符串就是一系列Unicode码的集合. 我们都知道,世界上存在着各种各样的语言,汉语,英语,日语等,相对应的,也就存在各种 ...

  5. puppet一个完整的实例

    一个具体实例来简单说明puppet的具体结构 创建第一个配置 puppet的组成清单这主要包含这几个部分 资源,文件,模板,节点,类,定义 puppet中有个模块的定义,这个比较重要,基本是puppe ...

  6. 图灵机器人API接口

    调用图灵API接口实现人机交互 流程一: 注册 图灵机器人官网: http://www.tuling123.com/ 第一步: 先注册, 然后创建机器人, 拿到一个32位的key 编码方式 UTF-8 ...

  7. CetenOS 6.9 搭建hubot运维机器人

    前言 Hubot是由Github开发的开源聊天机器人,基于Node.js采用CoffeeScript编写 可以借助Hubot开发Chatbot来自动化的完成想要一切自动化任务,比如: -运维自动化(编 ...

  8. day5 range 用法示例

    函数语法 range(start, stop[, step]) 参数说明: start: 计数从 start 开始.默认是从 0 开始.例如range(5)等价于range(0, 5); stop: ...

  9. MT【284】构造函数的导数的两类题型

    第一类: 已知定义在$R$上的奇函数$f(x),f(-1)=0,$当$x>0$时,$xf^{'}(x)-f(x)<0,$则$f(x)>0$的解集为____ 第二类: 已知函数$f(x ...

  10. 常用LaTeX随时更

    连乘 \prod_{i=1}^n \[\prod_{i=1}^n\] 分数 \frac{a}{b} \[\frac{a}{b}\] 组合数 \tbinom{n}{r}=\tbinom{n}{n-r}= ...