题目链接 \(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. 洛谷 p1092 虫食算

    题目链接: https://www.luogu.org/problemnew/show/P1092 这个题折腾了我好久 这其实本质上是一道凑算式的题目 ,让一个二维数组存算式,一个一位数组存字母分别代 ...

  2. Lodop中特殊符号¥打印设计和预览不同

    Lodop中¥符号样式改变问题 Lodop中对超文本样式的解析,虽然说是按照调用的本机ie引擎,但是调用的ie版本可能不同,导致在ie下是一种样式,预览又是另一种样式.可能是有些样式没有具体设置,走的 ...

  3. webpack 配置 publicPath的理解

    在学习webpack的时候,配置文件中有一个publicPath属性,一直不是很明白它到底是怎么用,也查了很多资料,得到最多的说法是当打包的时候,webpack会在静态文件路径前面添加publicPa ...

  4. Tyche 2191 WYF的递推式

    题目描述 WYF手中有这样一条递推式 WYF并不是想让你帮他做出结果,事实上,给定一个n,他能够迅速算出Fn.WYF只是想单纯的考验一下读者们. 输入描述 仅一行,三个整数N,F1,P 输出描述 仅一 ...

  5. 红米Note 7 Pro在印度首销迅速售罄

    3月13日消息,红米Note 7 Pro在印度率先发售. 小米印度业务负责人Manu Kumar Jain发推特表示,红米Note 7 Pro开售几秒钟就被抢光,我们的工厂正在加班加点工作,全力以赴提 ...

  6. excel导入、导出

    http://blog.csdn.net/cjh200102/article/details/12557599 NPOI 工作本HSSFWorkbook 构造方法,无参表示创建一个新的工作本,可以接收 ...

  7. P1130 红牌

    题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌.获得红牌的过程是相当复杂 ,一共包括NN个步骤.每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件.为了加快进程,每一步政府都派 ...

  8. 【BZOJ3809】Gty的二逼妹子序列 莫队 分块

    题目描述 给你一个长度为\(n\)的数列,还有\(m\)个询问,对于每个询问\((l,r,a,b)\),输出区间\([l,r]\)有多少范围在\([a,b]\)的权值. \(n\leq 100000, ...

  9. navicat激活

    参考:https://www.jianshu.com/p/5f693b4c9468 一开始想激活12.1.8,但是激活按钮一直点不了,换了个12.0激活成功

  10. [luogu4005]小Y和地铁【搜索+树状数组】

    传送门:https://www.luogu.org/problemnew/show/P4005 最简单的暴力拿最高的分,二进制爆搜. #include <bits/stdc++.h> #d ...