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加强版) 离线做法就不行了 我们就要用一个 ...
随机推荐
- Lodop打印旋转180度 倒着打
方法1:打印出来后,直接把纸张倒过来.如果本身是白纸,打印机出纸内容是倒着的,可以打出来后手动倒着把纸张正过来.如果本身不是白纸,需要打印的纸张上有背景,调整进纸方向.(如果是卷纸,卷纸背景是反的,查 ...
- SVG路径
前面的话 本文将详细介绍SVG路径 path字符串 路径(path)是一个非常强大的绘图工具,可以用path元素绘制矩形(直角矩形或者圆角矩形).圆形.椭圆.折线形.多边形,以及一些其他的形状,例如贝 ...
- 三种bean创建方式
- MobX基础 ----- 类的静态属性和装饰器
当我们使用MobX的时候,首先要声明一个store, 用来保存状态,它的最基本的语法 如下: class Todo { @observable title = ""; @obser ...
- codeforces616B
Dinner with Emma CodeForces - 616B Jack decides to invite Emma out for a dinner. Jack is a modest st ...
- Nginx 针对上游服务器缓存
L:99 nginx缓存 : 定义存放缓存的载体 proxy_cache 指令 Syntax: proxy_cache zone | off; Default: proxy_cache off; Co ...
- Codeforces 768B B. Code For 1
参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6423483.html B. Code For 1 time limit per test:2 se ...
- Django ORM模型
Object Relational Mapping(ORM) 一,ORM介绍 1, ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象 ...
- 【AGC005F】Many Easy Problems FFT 容斥原理
题目大意 给你一棵树,有\(n\)个点.还给你了一个整数\(k\). 设\(S\)为树上某些点的集合,定义\(f(S)\)为最小的包含\(S\)的联通子图的大小. \(n\)个点选\(k\)个点一共有 ...
- 【XSY2528】道路建设 LCT 可持久化线段树
题目描述 给你一个\(n\)个点\(m\)条边图,\(q\)个询问,每次问你边权在\([l,r]\)之间的边组成的最小生成树(森林)的边权和.强制在线. \(n,m,q\leq 100000\) 题解 ...