[BZOJ 3551] Peaks 半可持久化并查集 可持久化线段树合并

实现

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cctype>
  5 #include <algorithm>
  6 #include <map>
  7 using namespace std;
  8 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
  9 inline int rd(void) {
 10     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
 11     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
 12 }
 13
 14 const int N = 100005;
 15 const int M = 500005;
 16 const int S = 5000000;
 17 const int INF = ~0u>>2;
 18
 19 int n, m, q, h[N];
 20 int Hash[N], idx;
 21 void Descrete(void) {
 22     F(i, 1, n) Hash[++idx] = h[i];
 23     sort(Hash+1, Hash+idx+1);
 24     idx = unique(Hash+1, Hash+idx+1) - Hash - 1;
 25     F(i, 1, n) h[i] = lower_bound(Hash+1, Hash+idx+1, h[i]) - Hash;
 26 }
 27
 28 struct E {
 29     int u, v, d;
 30     friend inline bool operator < (E A, E B) { return A.d < B.d; }
 31 }e[M];
 32
 33 int f[N], s[N], w[N];
 34 inline int Find(int x, int d = INF) {
 35     while (x != f[x] && d >= w[x])
 36         x = f[x];
 37     return x;
 38 }
 39
 40 int tot, Froot[N]; map<int, int> root[N];
 41 int c[S][2], cnt[S];
 42
 43 inline void Insert(int &x, int L, int R, int w) {
 44     cnt[x = ++tot] = 1;
 45     if (L == R) return;
 46     int M = (L+R)>>1;
 47     w <= M ? Insert(c[x][0], L, M, w) : Insert(c[x][1], M+1, R, w);
 48 }
 49 inline int Merge(int x, int y) {
 50     if (!x || !y) return x+y;
 51     int z = ++tot; cnt[z] = cnt[x] + cnt[y];
 52     c[z][0] = Merge(c[x][0], c[y][0]);
 53     c[z][1] = Merge(c[x][1], c[y][1]);
 54     return z;
 55 }
 56 inline int Query(int x, int L, int R, int K) {
 57     if (L == R) return L;
 58     int M = (L+R)>>1;
 59     return K <= cnt[c[x][1]] ? Query(c[x][1], M+1, R, K) : Query(c[x][0], L, M, K - cnt[c[x][1]]);
 60 }
 61
 62 int main(void) {
 63     #ifndef ONLINE_JUDGE
 64         freopen("xsy1661.in", "r", stdin);
 65     #endif
 66
 67     n = rd(), m = rd(), q = rd();
 68     F(i, 1, n) h[i] = rd();
 69     Descrete();
 70
 71     F(i, 1, m) {
 72         int u = rd(), v = rd(), d = rd();
 73         e[i] = (E){ u, v, d };
 74     }
 75     sort(e+1, e+m+1);
 76
 77     F(i, 1, n) f[i] = i, s[i] = 0, w[i] = INF;
 78     F(i, 1, n) {
 79         Insert(Froot[i], 1, idx, h[i]);
 80         root[i][-INF] = Froot[i];
 81     }
 82
 83     for (int i = 1, T = 1; i <= m && T <= n; i++) {
 84         int u = e[i].u, v = e[i].v, d = e[i].d;
 85         int fu = Find(u), fv = Find(v);
 86         if (fu == fv) continue; T++;
 87         if (s[fu] > s[fv]) swap(fu, fv);
 88         f[fu] = fv, s[fv] += (s[fv] == s[fu]), w[fu] = d;
 89         root[fv][d] = Froot[fv] = Merge(Froot[fv], Froot[fu]);
 90     }
 91
 92     F(i, 1, q) {
 93         int x = rd(), d = rd(), K = rd();
 94         int t = Find(x, d);
 95         map<int, int>::iterator it = root[t].upper_bound(d);
 96         int rt = (--it) -> second;
 97         if (K < 1 || K > cnt[rt])
 98             puts("-1");
 99         else printf("%d\n", Hash[Query(rt, 1, idx, K)]);
100     }
101
102     return 0;
103 }
时间: 2024-08-10 17:38:21

[BZOJ 3551] Peaks 半可持久化并查集 可持久化线段树合并的相关文章

BZOJ 3674 可持久化并查集加强版(主席树变形)

3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 2515  Solved: 1107 [Submit][Status][Discuss] Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n,m<=2*10^4 Input Output Sample Inp

【BZOJ-3673&amp;3674】可持久化并查集 可持久化线段树 + 并查集

3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status][Discuss] Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n,m<=2*10^4 Input Output Sample Input 5 6

半可持久化并查集

对于常见的可持久化并查集, 我们可以通过 按秩合并 + 可持久化数组 . 但是, 此半可持久化并查集, 非彼可持久化并查集. 我们不用支持时间旅行, 即不用支持回到过去的某个版本, 而只用储存历史信息. 举个例子来说吧. n 个点, 支持两种操作: ① 将某两个点之间连边; ② 查询在前 t 次操作下, 某两个点是否连通. 强制在线. 核心模型 给定 n 个点, m 条带权边的无向图. 求在所有边权不超过 d 的边的作用下, 某个点或某两个点的连通性信息. 强制在线. 之前举的那个例子也可以这样

可持久化并查集加强版 BZOJ 3674

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 3674: 可持久化并查集加强版 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 3225  Solved: 1192[Submit][Status][Discuss] Description Description:自从zkysb出了可持久化并查集后--hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可

BZOJ 3673: 可持久化并查集 by zky

3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2084  Solved: 941[Submit][Status][Discuss] Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n,m<=2*10^4 Input Output Sample Input 5 6

BZOJ 3674: 可持久化并查集加强版

3674: 可持久化并查集加强版 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 2605  Solved: 977[Submit][Status][Discuss] Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状

【BZOJ】3673: 可持久化并查集 by zky &amp; 3674: 可持久化并查集加强版(可持久化线段树)

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 http://www.lydsy.com/JudgeOnline/problem.php?id=3673 双倍经验啦啦啦.. 给主席树换了个名称果然高大上... 首先要可持久化并查集其实就是可持久化数组... 那么因为数组的形式是这样的$P[x]$,那么我们用一种数据结构实现查找x返回对应的$P[x]$即可啦啦啦. 然后那么我所学的可持久化目前只有主席树QAQ哪天去写写fhqtreap...

BZOJ 3673 可持久化并查集 by zky &amp;&amp; 3674 可持久化并查集加强版

题目大意:维护一种数据结构实现可持久化并查集. 思路:利用可持久化线段树实现可持久化数组维护可持久化并查集.(不知道3674哪里加强了... CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define RANGE 8000010 #define MAX 200200 using namespace std; struct SegTree

BZOJ 3673 可持久化并查集 by zky 可持久化并查集

题目大意:给定n个集合,提供三种操作: 1.合并a,b所在集合 2.回到第k次操作之后的状态 3.询问a,b是否在同一集合 可持久化并查集0.0 实现方式是用可持久化线段树实现可持久化数组维护可持久化并查集... 至于可持久化数组,每条路径上只有叶节点的位置的num域是有意义的,感觉无比浪费0.0 可是不这样还真没法维护0.0 合并时本来应该按照每个节点的深度之和维护,结果手残懒得写,只用siz维护了0.0 至于路径压缩,写了比不写慢0.0 还是不写了吧 #include<cstdio> #i