题目链接 \(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. python之range()函数、for-in循环和while循环

    range()函数和for-in循环 函数原型:range(start, end, scan): 参数含义:start:计数从start开始.默认是从0开始.例如range(5)等价于range(0, ...

  2. 百度编辑器UEditor使用方法

    http://www.cnblogs.com/lionden/archive/2012/07/13/ueditor.html 介绍图片上传:http://uikoo9.com/blog/detail/ ...

  3. webpack配置之代码优化

    前面的话 前面介绍了webpack的基本配置,本文将详细介绍webpack中关于代码优化的配置 打包公共代码 CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 ch ...

  4. Cisco IP 电话 将它的voice mail 发送到手机

    功能一.将语音转成文字发送短信(有微软认知.百度认知.云片短信API) 功能二.直接将音频发送到微信 不废话,直接送个包 链接: https://github.com/JaviZhu/KLCN.Spe ...

  5. Linux成为云计算平台的主流操作系统

    导读 这是一个人人谈"云"."大数据"的时代,作为一个IT民工,如果与同行间聊天时,不谈及这方面的内容,有人可能会觉得你落伍了,跟不上这个时代了. 这是一个人人 ...

  6. 洛谷P1414又是毕业季二题解

    题目 思想: 首先这个题必定是一个数学题,肯定不是一个一个枚举得到解,这样肯定会T,所以我们就应该想一些别的方法,. 分析: 比如,答案,一定是递减的,因为该答案所满足的条件肯定是越来越苛刻的,所以我 ...

  7. 洛谷P1781宇宙总统题解

    题目 此题原本是一个简单的排序,但因为数据范围的限制,所以变成了一个需采用字符串排序的题目,接下来我将给大家讲一下如何字符串排序. 首先先判断为位数上是否相同,如果不同再比较那一位的数就可以了 #in ...

  8. Appium+python+html生成饼图测试报告

    历时三周这个小框架终于正式运行了,git源码地址;https://github.com/jiyanjiao/AutoTEST/tree/master/qingqi_driver_app 报告如图:

  9. 【XSY2484】mex 离散化 线段树

    题目大意 给你一个无限长的数组,初始的时候都为\(0\),有3种操作: 操作\(1\)是把给定区间\([l,r]\)设为\(1\): 操作\(2\)是把给定区间\([l,r]\)设为\(0\): 操作 ...

  10. 深度分析Java的枚举类型—-枚举的线程安全性及序列化问题

    原文:深度分析Java的枚举类型--枚举的线程安全性及序列化问题 枚举是如何保证线程安全的 要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和clas ...