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加强版的更多相关文章

  1. BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]

    3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...

  2. bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Stat ...

  3. bzoj 3551: [ONTAK2010]Peaks加强版

    Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...

  4. bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

    Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...

  5. BZOJ.3551.[ONTAK2010]Peaks加强版(Kruskal重构树 主席树)

    题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. 强制在线. \ ...

  6. 【刷题】BZOJ 3551 [ONTAK2010]Peaks加强版

    Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...

  7. BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增

    建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...

  8. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  9. [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)

    3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2438  Solved: 763[Submit][ ...

随机推荐

  1. char *转string遇到诡异的问题记录

    这个问题的背景是在用libevent的buffer_remove时出现的,写一个伪代码 char buffer[2048] ={0}; string str; int n = buffer_remov ...

  2. (转)浅谈PostgreSQL的索引

    1. 索引的特性 1.1 加快条件的检索的特性 当表数据量越来越大时查询速度会下降,在表的条件字段上使用索引,快速定位到可能满足条件的记录,不需要遍历所有记录. create table t(id i ...

  3. 洛谷 P3175 [HAOI2015]按位或

    题目分析 与hdu4336 Card Collector相似,使用min-max容斥. 设\(\max(S)\)表示集合\(S\)中最后一位出现的期望时间. 设\(\min(S)\)表示集合\(S\) ...

  4. 十.mysqld_multi stop无效问题

    今天在尝试运行mysqld_report stop的时候,发现无法停止mysql,日志中的错误如下 Stopping MySQL servers mysqladmin: [Warning] Using ...

  5. Gluon.vision的几类数据集

    http://mxnet.apache.org/api/python/gluon/data.html import mxnet as mx from mxnet import nd,autograd, ...

  6. [JSOI2016]最佳团体

    嘟嘟嘟 01分数规划+树形背包. 然后就没了. 结果我调了半天,原因还是树形背包不熟练. 我是用dfs序求的,转化的时候,是dp[i][j]转化到dp[i + 1][j + 1]或dp[i +siz[ ...

  7. Python常用库之一:Numpy

    Numpy支持大量的维度数组和矩阵运算,对数组运算提供了大量的数学函数库! Numpy比Python列表更具优势,其中一个优势便是速度.在对大型数组执行操作时,Numpy的速度比Python列表的速度 ...

  8. Hive之数据类型

    Hive之数据类型   (本文是基于多篇文章根据个人理解进行的整合,参考的文章见末尾的整理) 数据类型 Hive支持两种数据类型,一类叫原子数据类型,一类叫复杂数据类型.原子数据类型包括数值型.布尔型 ...

  9. 视图 b

  10. HDU 2082 找单词 (普通型 数量有限 母函数)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2082 找单词 Time Limit: 1000/1000 MS (Java/Others)    Me ...