3551: [ONTAK2010]Peaks加强版

3551: [ONTAK2010]Peaks加强版

https://www.lydsy.com/JudgeOnline/problem.php?id=3551

分析:

  kruskal重构树 +  倍增 + 主席树。

  首先建立kruskal重构树,那么查询就变成了,在kruskal重构树上找倍增找到最上面的权值小于x的点(节点的权值为原图的边权),那么这棵树内的所有点都可以在经过权值小于x的点相互到达,所以在这棵树内查询第k大即可。dfs序后,变成序列上的问题,查询区间的第k大。

代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<cctype>
  7 #include<set>
  8 #include<vector>
  9 #include<queue>
 10 #include<map>
 11 #define fi(s) freopen(s,"r",stdin);
 12 #define fo(s) freopen(s,"w",stdout);
 13 using namespace std;
 14 typedef long long LL;
 15 
 16 inline int read() {
 17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 19 }
 20 
 21 const int N = 100005;
 22 
 23 struct Edge{
 24     int u, v, w;
 25     bool operator < (const Edge &A) const {
 26         return w < A.w;
 27     }    
 28 }e[500005];
 29 int fa[N << 1], f[N << 1][19], mx[N << 1], st[N << 1], pos[N << 1], en[N << 1], val[N], disc[N]; // mx[N<<1] 
 30 int sum[N * 18], ls[N * 18], rs[N * 18], Root[N << 1]; // 乘18,不要17 
 31 int n, m, Q, tot, Time_Index, tot_node;
 32 vector<int> T[N << 1];
 33 
 34 #define lson l, mid, rt << 1
 35 #define rson mid + 1, r, rt << 1 | 1
 36 
 37 int find(int x) {
 38     return x == fa[x] ? x : fa[x] = find(fa[x]);
 39 }
 40 void Kruskal() {
 41     for (int i=1; i<=n+n; ++i) fa[i] = i;
 42     sort(e + 1, e + m + 1);
 43     int cntedge = 0; tot = n;
 44     for (int i=1; i<=m; ++i) {
 45         int u = find(e[i].u), v = find(e[i].v);
 46         if (u == v) continue;
 47         ++tot;
 48         fa[u] = tot, fa[v] = tot;
 49         f[u][0] = tot, f[v][0] = tot;
 50         mx[tot] = e[i].w;
 51         T[tot].push_back(u), T[tot].push_back(v);
 52 //        if (++cntedge == n + n - 1) break; // n + n - 1
 53     }
 54 }
 55 void dfs(int u,int fa) {
 56     st[u] = ++Time_Index;
 57     pos[Time_Index] = u;
 58     for (int sz=T[u].size(),i=0; i<sz; ++i) {
 59         int v = T[u][i];
 60         if (v == fa) continue;
 61         dfs(v, u);
 62     }
 63     en[u] = Time_Index;
 64 }
 65 void update(int l,int r,int &rt,int last,int p) {
 66     rt = ++tot_node;
 67     sum[rt] = sum[last] + 1;
 68     ls[rt] = ls[last], rs[rt] = rs[last];
 69     if (l == r) return ;
 70     int mid = (l + r) >> 1;
 71     if (p <= mid) update(l, mid, ls[rt], ls[last], p);
 72     else update(mid + 1, r, rs[rt], rs[last], p);
 73 }
 74 int query(int l,int r,int Head,int Tail,int k) {
 75     if (sum[Tail] - sum[Head] < k) return -1;
 76     if (l == r) return l;
 77     int mid = (l + r) >> 1, cnt = sum[ls[Tail]] - sum[ls[Head]];
 78     if (cnt >= k) return query(l, mid, ls[Head], ls[Tail], k);
 79     else return query(mid + 1, r, rs[Head], rs[Tail], k - cnt);    
 80 }
 81 int main() {
 82     n = read(), m = read(), Q = read();
 83     for (int i=1; i<=n; ++i) val[i] = read(), disc[i] = val[i];
 84     for (int i=1; i<=m; ++i) 
 85         e[i].u = read(), e[i].v = read(), e[i].w = read();
 86     
 87     sort(disc + 1, disc + n + 1);
 88     int cnt = 1;
 89     for (int i=2; i<=n; ++i) if (disc[i] != disc[cnt]) disc[++cnt] = disc[i]; // i=2
 90     for (int i=1; i<=n; ++i) val[i] = lower_bound(disc + 1, disc + cnt + 1, val[i]) - disc;
 91     
 92     Kruskal();
 93     dfs(tot, 0);
 94     
 95     for (int j=1; j<=18; ++j) 
 96         for (int i=1; i<=tot; ++i) f[i][j] = f[f[i][j-1]][j-1];
 97     
 98     for (int i=1; i<=tot; ++i) {
 99         if (pos[i] > n) Root[i] = Root[i - 1];
100         else update(1, cnt, Root[i], Root[i - 1], val[pos[i]]); // val[pos[i]] !!!
101     }
102     
103     int lastans = 0;
104     while (Q--) {
105         int v = read(), x = read(), k = read();
106         if (lastans != -1) v ^= lastans, x ^= lastans, k ^= lastans; 
107         for (int i=18; i>=0; --i)     
108             if (f[v][i] && mx[f[v][i]] <= x) v = f[v][i];
109         int l = st[v], r = en[v];
110         k = sum[Root[r]] - sum[Root[l]] - k + 1;
111         if (k <= 0) { puts("-1"); lastans = -1; continue; }
112         int p = query(1, cnt, Root[l], Root[r], k);
113         if (p == -1) { puts("-1"); lastans = -1; continue; }
114         printf("%d
",lastans = disc[p]);
115     }
116     return 0;
117 }
原文地址:https://www.cnblogs.com/mjtcn/p/9675447.html