【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)
Description
在\(Bytemountains\)有\(~n~\)座山峰,每座山峰有他的高度\(~h_i~\)。 有些山峰之间有双向道路相连,共\(~m~\)条路径,每条路径有一个困难值,这个值越大表示越难走,现在有\(~q~\)组询问,每组询问询问从点\(~v~\)开始只经过困难值小于等于\(~x~\)的路径所能到达的山峰中第\(~k~\)高的山峰,如果无解输出\(-1\)。强制在线。
Solution
把边从小到大排序插入\(kruskal\)重构树中,对于每次询问, 倍增求出\(~v~\)祖先中第一个小于\(~x~\)的瓶颈,子树第\(~k~\)大用主席树维护即可,只不过主席树记的是第\(~k~\)小的值,记得要反过来查询。
Code
#include<bits/stdc++.h>
#define For(i, j, k) for(int i = j; i <= k; ++i)
#define Forr(i, j, k) for(int i = j; i >= k; --i)
#define Travel(i, u) for(int i = beg[u], v = to[i]; i; i = nex[i], v = to[i])
using namespace std;
inline int read() {
int x = 0, p = 1; char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') p = -1;
for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x *= p;
}
inline void File() {
#ifndef ONLINE_JUDGE
freopen("bzoj3545.in", "r", stdin);
freopen("bzoj3545.out", "w", stdout);
#endif
}
const int N = 2e5 + 10, M = N << 2, MAXE = 5e5 + 10;
int n, m, q, st[N], ed[N], h[N], F[20][N], cnt, clk, ls[N], lstans;
int e = 1, beg[N], nex[M], to[M], fa[N], pos[N], rt[N], tot, hh[N], id[N];
struct edge { int u, v, w; } E[MAXE];
inline void add(int x, int y) { to[++ e] = y, nex[e] = beg[x], beg[x] = e; }
inline bool cmp(const edge &a, const edge &b) { return a.w < b.w; }
inline int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
inline void dfs(int u, int f) { pos[st[u] = ++ clk] = u; Travel(i, u) dfs(v, u); ed[u] = clk; }
inline void rebuild() {
For(i, 1, n << 1) fa[i] = id[i] = i;
For(i, 1, m) E[i].u = read(), E[i].v = read(), E[i].w = read();
sort(E + 1, E + 1 + m, cmp);
For(i, 1, m) {
int u = E[i].u, v = E[i].v;
if (find(u) == find(v)) continue;
u = fa[u], v = fa[v], hh[++ cnt] = E[i].w;
add(cnt, u), add(cnt, v); fa[u] = fa[v] = cnt;
F[0][u] = F[0][v] = cnt;
}
F[0][cnt] = cnt; dfs(cnt, cnt);
}
namespace Segment_Tree {
#define mid (l + r >> 1)
int c = 0; struct node { int lc, rc, v; } tr[N * 30];
inline void update(int &now, int pre, int l, int r, int rk) {
now = ++ c, tr[now] = tr[pre], ++ tr[now].v;
if (l < r) {
if (rk <= mid)
update(tr[now].lc, tr[pre].lc, l, mid, rk);
else
update(tr[now].rc, tr[pre].rc, mid + 1, r, rk);
}
}
inline int query(int u, int v, int l, int r, int rk) {
if (l == r) return l;
int num = tr[tr[v].lc].v - tr[tr[u].lc].v;
if (rk <= num)
return query(tr[u].lc, tr[v].lc, l, mid, rk);
else
return query(tr[u].rc, tr[v].rc, mid + 1, r, rk - num);
}
#undef mid
}
using namespace Segment_Tree;
inline void LS() {
sort(ls + 1, ls + 1 + n);
tot = unique(ls + 1, ls + 1 + n) - ls - 1;
For(i, 1, n) h[i] = lower_bound(ls + 1, ls + 1 + tot, h[i]) - ls;
For(i, 1, cnt) {
if (pos[i] <= n)
update(rt[i], rt[i - 1], 1, tot, h[pos[i]]);
else
rt[i] = rt[i - 1];
}
For(j, 1, 18) For(i, 1, cnt) F[j][i] = F[j - 1][F[j - 1][i]];
}
int main() {
File();
cnt = n = read(), m = read(), q = read();
For(i, 1, n) ls[i] = h[i] = read();
rebuild(), LS();
while (q --) {
int v = read(), x = read(), k = read();
if (lstans != -1) v ^= lstans, x ^= lstans, k ^= lstans;
Forr(i, 18, 0) if (hh[F[i][v]] <= x) v = F[i][v];
int res = tr[rt[ed[v]]].v - tr[rt[st[v] - 1]].v;
if (res < k) puts("-1"), lstans = -1;
else {
lstans = ls[query(rt[st[v] - 1], rt[ed[v]], 1, tot, res - k + 1)];
printf("%d\n" ,lstans);
}
}
return 0;
}
【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)的更多相关文章
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- 【BZOJ3545】Peaks(Kruskal重构树 主席树)
题目链接 大意 给出有\(N\)个点\(M\)条边的一张图,其中每个点都有一个High值,每条边都有一个Hard值. 再给出\(Q\)个询问:\(v\) \(x\) \(k\) 每次询问查询从点\(v ...
- luogu4197 Peaks (kruskal重构树+主席树)
按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...
- 洛谷P4197 Peaks(Kruskal重构树 主席树)
题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...
- [ONTAK2010]Peaks kruskal重构树,主席树
[ONTAK2010]Peaks kruskal重构树练手题. LG传送门竟然不强制在线?看到离线水过很不爽:B站强制在线版传送门 看到"询问从点\(v\)开始只经过困难值小于等于\(x\) ...
- luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)
题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- bzoj 3545: [ONTAK2010]Peaks Kruskal重构树
题目: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...
随机推荐
- HNOI2016做题笔记
HNOI2016 最小公倍数 (分块.并查集) 看到这种不能用数据结构(实际上是可以用K-D Tree的)维护的题目就应该想到分块然后使用并查集维护连通性和一个连通块中的\(maxa , maxb\) ...
- Luogu4697 CEOI2011 Balloons 单调栈
传送门 题意:给出$N$个气球,从左往右给出它们的$x_i$与$r_i$.现在从左往右给它们充气,每一个气球在充气的过程中始终在$x_i$点与地面相切,且最大半径为$r_i$.如果在充气的过程中气球与 ...
- C#深入理解AutoResetEvent和ManualResetEvent
当在C#使用多线程时就免不了使用AutoResetEvent和ManualResetEvent类,可以理解这两个类可以通过设置信号来让线程停下来或让线程重新启动,其实与操作系统里的信号量很相似(汗,考 ...
- 在 Linux 上搭建IntelliJ IDEA license server服务器
IntelliJIDEALicenseServer_linux_amd64 ,把该文件传到服务器的某个目录,我是放在了/var/local/software目录下 sudo chmod +x ./In ...
- C. Ehab and a 2-operation task
链接 [https://codeforces.com/contest/1088/problem/C] 题意 n个数,最多n+1操作,要么前i个数加x,要么前i个数对x取余,最后使得严格递增 分析 直接 ...
- 《linux内核设计与实现》第四章
调度程序负责决定哪个进程投入运行,何时运行以及运行多长时间.只有通过调度程序合理调度,系统资源才能最大限度发挥作用,多进程才会有并发执行的效果. 最大限度地利用处理器时间的原则是,只要有可以执行的进程 ...
- 20135337——Linux实践三:ELF文件格式(64位系统,简单分析)
ELF文件格式简单分析 (具体分析见上一篇ELF文件格式32位系统) ELF-header 第一行: 457f 464c :魔数: 0201 :64位系统,小端法 01 :文件头版本 剩余默认0: 第 ...
- JavaScript —— 数组
Array方法 1.查找元素 indexOf()用来查找传进来的参数在目标数组中是否存在.如果目标数组包含该参数,就返回该元素在数组中的索引:如果不包含,就返回-1. 如果数组中包含多个相同的元素,i ...
- 个人项目Individual Project:迷宫求解
源码的github链接: https://github.com/zhangxue520/test 1.1问题描述: a.问题描述:以一个m * n的长方阵表示迷宫,0和1分别表示迷 ...
- 小学四则运算APP 第二阶段冲刺-第三天
团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第二次冲刺阶段时间:11.29~12.09 本次发布的是判断题的部分代码 panduanset.java import com.examp ...