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][ ...
随机推荐
- 不规矩的xml与JAVA对象互相转换的小技巧-使用Marshaller
摘要:将XML文档与JAVA对象互转是很常见的需求,如果XML定义很规整这很好实现.然而在现实中“不规矩”的XML可能更常见,Marshaller便无能为力了吗?下面是一个小技巧,调整一下思维便能重用 ...
- Hibernate双向一对多、双向多对多关联关系中的映射文件怎么写
这里以一对多关联关系为例.以Country类为一端,Competition类为多端. 一个国家可以有多个赛事,但是一个赛事只能属于一个国家. Country类 public class Country ...
- BIND简易教程(0):在Ubuntu下源码安装BIND(其实跟前面的教程没太大关系)
之前介绍过BIND的基本使用啦.关于BIND的入门级使用方法见:http://www.cnblogs.com/anpengapple/p/5877661.html简易教程系列,本篇只讲BIND安装. ...
- ORACLE查询删除重复记录
比如现在有一人员表 (表名:peosons) 若想将姓名.身份证号.住址这三个字段完全相同的记录查询出来 复制代码 代码如下: select p1.* from persons p1,pers ...
- boost::timer库使用
boost::timer boost库定时器使用,需要在编译时加相关链接库 -lboost_timer -lboost_system boost::timer::cpu_timer 和boost::t ...
- vue - 数据驱动,组件化, 双向绑定原理
1.数据驱动 传统的前端数据交互是用Ajax从服务端获取数据,然后操作DOM来改变视图: Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层.它让 ...
- 在eclipse中查看HttpServlet源码失败的解决方法
在初次建立java EE 项目时,想要查看HttpServlet源码时会提示失败, 按照网上的方式,将Tomcat中lib中的servlet-api.jar的包导进去,发现并不管用.并且提示里面并不包 ...
- GPIO 配置示例
概述:学习STM32的GPIO configration /********************************************************************** ...
- Spring - 父容器与子容器
一.Spring容器(父容器) 1.Mapper代理对象 2.Service对象 二.Springmvc(前端控制器)(子容器) Controller对象 1.标准的配置是这样的:Con ...
- Java中的IO流(四)
上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...