首页 > 代码库 > [BZOJ 3551] Peaks 半可持久化并查集 可持久化线段树合并

[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 }

 

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