洛谷P4197 Peaks(Kruskal重构树 主席树)
题意
往后中文题就不翻译了qwq
Sol
又是码农题。。出题人这是强行把Kruskal重构树和主席树拼一块了啊。。
首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的。
考虑把Kruskal重构树建出来,重构树上每个新的节点代表的是边权,同时用倍增数组维护出跳2^i步后能走到的值最大的节点
这样,该节点的整个子树内的节点都是可以走到的。
用dfs序+主席树维护出每个节点内H的值,直接查第K大即可
需要注意的是,对于不在原树内的节点,H要设的非常小,或者不插入,以免对答案产生影响
同时H需要离散化
写+调用了整两个小时,,自己的码力还是太弱了qwq
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
using namespace std;
const int MAXN = 1e6 + ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int N, M, Q, H[MAXN], date[MAXN], tot, num = ;
struct Edge {
int u, v, w;
bool operator < (const Edge &rhs) const {
return w < rhs.w;
}
}E[MAXN];
void AddEdge(int x, int y, int z) {E[++num] = (Edge) {x, y, z};}
int fa[MAXN], fd[MAXN][], dis[MAXN][];
int find(int x) {
if(fa[x] == x) return fa[x];
else return fa[x] = find(fa[x]);
}
int unionn(int x, int y) {fa[x] = y;}
vector<int> v[MAXN];
void Build() {
for(int i = ; i <= (N << ); i++) fa[i] = i;
sort(E + , E + num + );
for(int i = ; i <= num; i++) {
int x = E[i].u, y = E[i].v, w = E[i].w;
int fx = find(x), fy = find(y);
if(fx == fy) continue;
tot++;
fa[fx] = tot; fa[fy] = tot;
v[fx].push_back(tot); v[fy].push_back(tot);
v[tot].push_back(fx); v[tot].push_back(fy);
dis[fx][] = w; dis[fy][] = w;
fd[fx][] = tot; fd[fy][] = tot;
if(tot == * N - ) break;
}
}
int ls[MAXN * ], rs[MAXN * ], Tsiz[MAXN * ], root[MAXN], cnt, siz[MAXN], dfn[MAXN], tra[MAXN];
void dfs(int x, int fa) {
dfn[x] = ++cnt; tra[dfn[x]] = x; siz[x] = ;
for(int i = ; i < v[x].size(); i++) {
int to = v[x][i];
if(to == fa) continue;
dfs(to, x);
siz[x] += siz[to];
}
}
void update(int k) {
Tsiz[k] = Tsiz[ls[k]] + Tsiz[rs[k]];
}
void Insert(int &k, int p, int val, int l, int r) {
k = ++cnt;
ls[k] = ls[p]; rs[k] = rs[p]; Tsiz[k] = Tsiz[p];
if(val == -) return ;
Tsiz[k]++;
if(l == r) return ;
int mid = l + r >> ;
if(val <= mid) Insert(ls[k], ls[p], val, l, mid);
else Insert(rs[k], rs[p], val, mid + , r);
update(k);
}
void MakeTree() {
cnt = ;
for(int i = ; i <= tot; i++)
Insert(root[i], root[i - ], H[tra[i]], , N);
}
void Jump() {
for(int j = ; j <= ; j++) {
for(int i = ; i <= tot; i++) {
fd[i][j] = fd[fd[i][j - ]][j - ];
dis[i][j] = max(dis[fd[i][j - ]][j - ], dis[i][j - ]);
}
}
}
int Get(int x, int val) {
for(int i = ; i >= ; i--)
if(dis[x][i] <= val && fd[x][i] != )
x = fd[x][i];
return x;
}
int Query(int lt, int rt, int k, int l, int r) {
int used = Tsiz[rs[rt]] - Tsiz[rs[lt]];
if(l == r) {
if(Tsiz[rt] - Tsiz[lt] < k) return -;
else return l;
}
int mid = l + r >> ;
if(k <= used) return Query(rs[lt], rs[rt], k, mid + , r);
else return Query(ls[lt], ls[rt], k - used, l, mid);
}
main() {
//freopen("1.in", "r", stdin);
//freopen("a.out", "w", stdout);
tot = N = read(); M = read(); Q = read();
memset(H, -, sizeof(H));
for(int i = ; i <= N; i++) H[i] = read(), date[i] = H[i];
sort(date + , date + N + );
int tmp = unique(date + , date + N + ) - date - ;
for(int i = ; i <= N; i++) H[i] = lower_bound(date + , date + N + , H[i]) - date;
for(int i = ; i <= M; i++) {
int x = read(), y = read(), z = read();
// v[x].push_back(MP(y, z));
// v[y].push_back(MP(x, z));
AddEdge(x, y, z); AddEdge(y, x, z);
}
Build();
dfs(tot, );
MakeTree();
Jump();
while(Q--) {
int v = read(), x = read(), k = read();
int top = Get(v, x);
int l = dfn[top], r = dfn[top] + siz[top] - ;
int ans = Query(root[l], root[r], k, , N);
if(ans == -) printf("%d\n", -);
else printf("%d\n", date[ans]);
}
return ;
}
洛谷P4197 Peaks(Kruskal重构树 主席树)的更多相关文章
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- luogu4197 Peaks (kruskal重构树+主席树)
按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...
- 【BZOJ3545】Peaks(Kruskal重构树 主席树)
题目链接 大意 给出有\(N\)个点\(M\)条边的一张图,其中每个点都有一个High值,每条边都有一个Hard值. 再给出\(Q\)个询问:\(v\) \(x\) \(k\) 每次询问查询从点\(v ...
- 【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)
Description 在\(Bytemountains\)有\(~n~\)座山峰,每座山峰有他的高度\(~h_i~\). 有些山峰之间有双向道路相连,共\(~m~\)条路径,每条路径有一个困难值 ...
- luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)
题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...
- [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)
题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
- LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...
随机推荐
- Arthur and Brackets
n<605设计出n对夸号 给出n个条件每个条件为[l,r] 表示第i对夸号右夸号离左夸号的距离,然后夸号的右夸号出现的顺序必须按照给的顺序 出现, 那么如果存在就输出否则输出impossilb ...
- 日志处理(二) 日志组件logback的介绍及配置使用方法(转)
本文转自:http://www.cnblogs.com/yuanermen/archive/2012/02/13/2348942.html http://www.cnblogs.com/yuanerm ...
- 解决android studio 模拟器取法启动声音的错误
Emulator: dsound: Reason: No sound driver is available https://jingyan.baidu.com/article/a65957f4348 ...
- 将flex页面嵌入到jsp页面中
如果我们只需要用到Flex的一部分功能,例如播放器功能,我们可以单独把Flex页面嵌入到Jsp页面中.要想实现此功能,需要下载一个工程,将其覆盖在服务器根目录下即可.你可以在次下载:FlexModul ...
- c++第十八天
p105~p108: 1.迭代器与数组的不同:迭代器的索引值必须是无符号类型,数组的索引无此要求. 2.使用数组的时候编译器一般会把它转化为指针. 3.auto ia2(数组名);的结果是:获得一个指 ...
- G_M_网络流A_网络吞吐量
调了两天的代码,到最后绝望地把I64d改成lld就过了,我真的是醉了. 网络吞吐量 题面:给出一张(n个点,m条边)带权(点权边权均有)无向图,点权为每个点每秒可以接受发送的最大值,边权为花费,保证数 ...
- Coursera SDN M1.1 SDN History: Central Control
source Structure 1.讨论SDN的时间线,从1980s至今. 2.认识到SDN背后的原则和idea. 3.识别SDN起源的架构主题. NOTE Four Chapter in SDN ...
- haskell简明入门(一)
本文的主要内容参考自<Haskell趣学指南> 1. What is Haskell? 以下内容引用自Haskell官网: Haskell是一个先进的,纯粹的函数式编程语言.一个典 ...
- Stub学习
RPC RPC(Remote Procedure Call)就是某台主机A(一般为client)像调用本地的过程一样去调用另一台主机B(一般为server)上的某个过程.RPC代码可能长成这个样子: ...
- 几个主流的Java连接池整理
池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对 ...