Luogu P4197 Peaks
题目链接 \(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的更多相关文章
- [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)
题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...
- BZOJ 3545 / 洛谷 P4197 Peaks 解题报告
P4197 Peaks 题目描述 在\(\text{Bytemountains}\)有\(N\)座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个 ...
- 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)
传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...
- P4197 Peaks
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点 ...
- 洛谷P4197 Peaks(Kruskal重构树 主席树)
题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...
- Luogu 4197 Peaks
BZOJ 3545 带权限. 考虑离线,把所有边按照从小到大的顺序排序,把所有询问也按照从小到大的顺序排序,然后维护一个并查集和一个权值线段树,每处理一个询问就把比这个询问的$x$更小的边连上,具体来 ...
- P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]
Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...
- 洛谷P4197 Peaks (Kruskal重构树)
读题,只经过困难值小于等于x的路径,容易想到用Kruskal重构树:又要查询第k高的山峰,我们选择用主席树求解. 先做一棵重构树,跑一遍dfs,重构树中每一个非叶子节点对应一段区间,我们开range[ ...
- kruscal重构树略解
我们先看一道题:Luogu P4197 Peaks 这道题珂以用启发式合并+主席树来做 那么强制在线呢?(bzoj 3551 [ONTAK2010]Peaks加强版) 离线做法就不行了 我们就要用一个 ...
随机推荐
- 转载 -- CSS3 中关于 select 下拉列表的样式
截图效果:
- @Html自定义属性
@Html.DropDownList("CardCode", (SelectList)ViewData["cardcodeselectlist"], " ...
- HTML5-Video视频-基础篇
展示视频 视频 <video width=" controls="controls"> <source src="movie.mp4" ...
- Python测试Post请求
原有: #coding:utf-8 import requests def request(title, content): datas = {"title":title,&quo ...
- github-share报错无法读取远程仓库
报错:github Could not read from remote repository 1.github创建仓库成功,而push报告此错误 2.考虑远程仓库名与本地项目名/文件夹名不匹配 3. ...
- 洛谷P2822 组合数问题
输入输出样例 输入样例#1: 1 2 3 3 输出样例#1: 1 输入样例#2: 2 5 4 5 6 7 输出样例#2: 0 7 说明 [样例1说明] 在所有可能的情况中,只有C_2^1 = 2C21 ...
- Educational Codeforces Round 62 (Rated for Div. 2)
A. Detective Book 题意:一个人读书 给出每一章埋的坑在第几页可以填完 . 一个人一天如果不填完坑他就会一直看 问几天能把这本书看完 思路:模拟一下 取一下过程中最大的坑的页数 如 ...
- 【Gym 100947I】What a Mess
BUPT 2017 summer training (for 16) #1D 题意 找到n个数里面有多少对具有倍数关系.\(1 ≤ n ≤ 10^4,2 ≤ a_i ≤ 10^6\) 题解 枚举一个数 ...
- dll 修复....
之前在安装时总是会碰到缺少什么dll文件,总是头疼的要命,这次很幸运的在网上搜到了这个神奇的小玩意,只需要运行就能够修复缺少的所有的dll文件,所以在这小小的分享一下. 链接:https://pan. ...
- Swarm stack
什么是 stack ?例如:首先创建 secret. 然后创建 MySQL service,这是 WordPress 依赖的服务. 最后创建 WordPress service. 也就是说,这个应用包 ...