3551: [ONTAK2010]Peaks加强版
3551: [ONTAK2010]Peaks加强版
https://www.lydsy.com/JudgeOnline/problem.php?id=3551
分析:
kruskal重构树 + 倍增 + 主席树。
首先建立kruskal重构树,那么查询就变成了,在kruskal重构树上找倍增找到最上面的权值小于x的点(节点的权值为原图的边权),那么这棵树内的所有点都可以在经过权值小于x的点相互到达,所以在这棵树内查询第k大即可。dfs序后,变成序列上的问题,查询区间的第k大。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; struct Edge{
int u, v, w;
bool operator < (const Edge &A) const {
return w < A.w;
}
}e[];
int fa[N << ], f[N << ][], mx[N << ], st[N << ], pos[N << ], en[N << ], val[N], disc[N]; // mx[N<<1]
int sum[N * ], ls[N * ], rs[N * ], Root[N << ]; // 乘18,不要17
int n, m, Q, tot, Time_Index, tot_node;
vector<int> T[N << ]; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1 int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void Kruskal() {
for (int i=; i<=n+n; ++i) fa[i] = i;
sort(e + , e + m + );
int cntedge = ; tot = n;
for (int i=; i<=m; ++i) {
int u = find(e[i].u), v = find(e[i].v);
if (u == v) continue;
++tot;
fa[u] = tot, fa[v] = tot;
f[u][] = tot, f[v][] = tot;
mx[tot] = e[i].w;
T[tot].push_back(u), T[tot].push_back(v);
// if (++cntedge == n + n - 1) break; // n + n - 1
}
}
void dfs(int u,int fa) {
st[u] = ++Time_Index;
pos[Time_Index] = u;
for (int sz=T[u].size(),i=; i<sz; ++i) {
int v = T[u][i];
if (v == fa) continue;
dfs(v, u);
}
en[u] = Time_Index;
}
void update(int l,int r,int &rt,int last,int p) {
rt = ++tot_node;
sum[rt] = sum[last] + ;
ls[rt] = ls[last], rs[rt] = rs[last];
if (l == r) return ;
int mid = (l + r) >> ;
if (p <= mid) update(l, mid, ls[rt], ls[last], p);
else update(mid + , r, rs[rt], rs[last], p);
}
int query(int l,int r,int Head,int Tail,int k) {
if (sum[Tail] - sum[Head] < k) return -;
if (l == r) return l;
int mid = (l + r) >> , cnt = sum[ls[Tail]] - sum[ls[Head]];
if (cnt >= k) return query(l, mid, ls[Head], ls[Tail], k);
else return query(mid + , r, rs[Head], rs[Tail], k - cnt);
}
int main() {
n = read(), m = read(), Q = read();
for (int i=; i<=n; ++i) val[i] = read(), disc[i] = val[i];
for (int i=; i<=m; ++i)
e[i].u = read(), e[i].v = read(), e[i].w = read(); sort(disc + , disc + n + );
int cnt = ;
for (int i=; i<=n; ++i) if (disc[i] != disc[cnt]) disc[++cnt] = disc[i]; // i=2
for (int i=; i<=n; ++i) val[i] = lower_bound(disc + , disc + cnt + , val[i]) - disc; Kruskal();
dfs(tot, ); for (int j=; j<=; ++j)
for (int i=; i<=tot; ++i) f[i][j] = f[f[i][j-]][j-]; for (int i=; i<=tot; ++i) {
if (pos[i] > n) Root[i] = Root[i - ];
else update(, cnt, Root[i], Root[i - ], val[pos[i]]); // val[pos[i]] !!!
} int lastans = ;
while (Q--) {
int v = read(), x = read(), k = read();
if (lastans != -) v ^= lastans, x ^= lastans, k ^= lastans;
for (int i=; i>=; --i)
if (f[v][i] && mx[f[v][i]] <= x) v = f[v][i];
int l = st[v], r = en[v];
k = sum[Root[r]] - sum[Root[l]] - k + ;
if (k <= ) { puts("-1"); lastans = -; continue; }
int p = query(, cnt, Root[l], Root[r], k);
if (p == -) { puts("-1"); lastans = -; continue; }
printf("%d\n",lastans = disc[p]);
}
return ;
}
3551: [ONTAK2010]Peaks加强版的更多相关文章
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 635 Solved: 177[Submit][Stat ...
- bzoj 3551: [ONTAK2010]Peaks加强版
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...
- bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...
- BZOJ.3551.[ONTAK2010]Peaks加强版(Kruskal重构树 主席树)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. 强制在线. \ ...
- 【刷题】BZOJ 3551 [ONTAK2010]Peaks加强版
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增
建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...
- 【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][ ...
随机推荐
- [原]零基础学习SDL开发之在Android使用SDL2.0显示BMP叠加图
关于如何移植在android上使用SDL,可以参考[原]零基础学习SDL开发之移植SDL2.0到Android 和 [原]零基础学习SDL开发之在Android使用SDL2.0显示BMP图 . 在一篇 ...
- 移动端开发 rem 案例
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 使用Hibernate注解Annotations进行对象映射的异常处理
通过Hibernate注解Annotations进行对象映射,想在Oracle数据库中自动创建表,代码如下: 实体类: import javax.persistence.Basic;import ja ...
- JAVA中高访问量高并发的问题怎么解决?
尽量使用缓存,包括用户缓存,信息缓存等,多花点内存来做缓存,可以大量减少与数据库的交互,提高性能. 用jprofiler等工具找出性能瓶颈,减少额外的开销. 优化数据库查询语句,减少直接使用hiber ...
- O(1) 和 O(n) 的区别
举个简单的例子,要从0加到n,我们会这么写:int sum = 0;for(int i = 0; i<=n; ++i){ sum += i;}一共算了n次加法,那么就说这个时间复杂度是O(n ...
- Django 创建模型 激活模型 简单的使用模型
创建模型: 在你的开发环境中,已经有一个“项目” —— 已经建立起来,你将开始在上面做一些东西. 你编写的每个Django应用都是一个遵循特定约定的Python包. Django自带一个工具,它可以自 ...
- 完整详解GCD系列(三)dispatch_group
http://blog.csdn.net/hello_hwc/article/details/41409135 一.dispatch_group把一组任务提交到队列中,这些队列可以不相关,然后坚挺这组 ...
- Unix shell输入输出重定向
敲代码的时候,适当地打印出一些进度或者日志信息经常能帮助我们跟踪程序的执行结果.可是,这些结果或者日志打印信息到屏幕上并不能作为以后检查问题的根据.这就是重定向的作用,敲代码的时候,我们能够方便的将相 ...
- 美化浏览器JSON格式
工具下载地址: https://github.com/weibanggang/JSON-handle 原始 优化后 直接将文件拖到浏览器即可
- 在js中获取request域中的内容
1.可以使用小脚本<%%>实现: var pro_id=<%request.getPro_id()%>; 2.使用隐藏域实现: <input type="hid ...