Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)

题目链接:https://www.spoj.com/problems/COT/en/

题目:

题意:

  给你一棵有n个节点的树,求节点u到节点v这条链上的第k大。

思路:

  我们首先用dfs进行建题目给的树,然后在dfs时进行主席树的update操作。众所周知,主席树采用的是前缀和思想,区间第k大是与前一个树添加新的线段树,而树上第k大则是与父亲节点添加新的线段树,因而在此思想上此题的答案为sum[u] + sum[v] - sum[lca(u,v)] - sum[fa[lca(u,v)]。求第k大操作和区间第k大一样,就不描述了~

代码实现如下:

 

  1 #include <set>
  2 #include <map>
  3 #include <queue>
  4 #include <stack>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <bitset>
  8 #include <cstdio>
  9 #include <string>
 10 #include <vector>
 11 #include <cstdlib>
 12 #include <cstring>
 13 #include <iostream>
 14 #include <algorithm>
 15 using namespace std;
 16 
 17 typedef long long LL;
 18 typedef pair<LL, LL> pLL;
 19 typedef pair<LL, int> pli;
 20 typedef pair<int, LL> pil;;
 21 typedef pair<int, int> pii;
 22 typedef unsigned long long uLL;
 23 
 24 #define lson rt<<1
 25 #define rson rt<<1|1
 26 #define lowbit(x) x&(-x)
 27 #define name2str(name) (#name)
 28 #define bug printf("*********\n");
 29 #define debug(x) cout<<#x"=["<<x<<"]" <<endl;
 30 #define FIN freopen("/home/dillonh/CLionProjects//in.txt", "r", stdin);
 31 #define FOUT freopen("D://code//out.txt", "w", stdout);
 32 #define IO ios::sync_with_stdio(false),cin.tie(0);
 33 
 34 const double eps = 1e-9;
 35 const int mod = 1000000007;
 36 const int maxn = 100000 + 7;
 37 const double pi = acos(-1);
 38 const int inf = 0x3f3f3f3f;
 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL;
 40 
 41 int n, q, tot, cnt, x, y, k, len;
 42 int head[maxn], root[maxn];
 43 int a[maxn], deep[maxn], fa[maxn][30];
 44 vector<int> v;
 45 
 46 struct edge {
 47     int v, next;
 48 }ed[maxn<<1];
 49 
 50 void addedge(int u, int v) {
 51     ed[tot].v = v;
 52     ed[tot].next = head[u];
 53     head[u] = tot++;
 54     ed[tot].v = u;
 55     ed[tot].next = head[v];
 56     head[v] = tot++;
 57 }
 58 
 59 struct node {
 60     int l, r, sum;
 61 }tree[maxn*40];
 62 
 63 int getid(int x) {
 64     return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
 65 }
 66 
 67 void update(int l, int r, int& x, int y, int pos) {
 68     tree[++cnt] = tree[y], tree[cnt].sum++, x = cnt;
 69     if(l == r) return;
 70     int mid = (l + r) >> 1;
 71     if(mid >= pos) update(l, mid, tree[x].l, tree[y].l, pos);
 72     else update(mid + 1, r, tree[x].r, tree[y].r, pos);
 73 }
 74 
 75 int query(int l, int r, int x, int y, int p, int pp, int k) {
 76     if(l == r) return l;
 77     int mid = (l + r) >> 1;
 78     int sum = tree[tree[x].l].sum + tree[tree[y].l].sum - tree[tree[p].l].sum - tree[tree[pp].l].sum;
 79     if(sum >= k) return query(l, mid, tree[x].l, tree[y].l, tree[p].l, tree[pp].l, k);
 80     else return query(mid + 1, r, tree[x].r, tree[y].r, tree[p].r, tree[pp].r, k - sum);
 81 }
 82 
 83 void dfs(int u, int d, int p) {
 84     deep[u] = d;
 85     fa[u][0] = p;
 86     update(1, len, root[u], root[p], getid(a[u]));
 87     for(int i = head[u]; ~i; i = ed[i].next) {
 88         int v = ed[i].v;
 89         if(v != p) {
 90             dfs(v, d + 1, u);
 91         }
 92     }
 93 }
 94 
 95 void lca() {
 96     for(int i = 1; i <= n; i++) {
 97         for(int j = 1; (1 << j) <= n; j++) {
 98             fa[i][j] = -1;
 99         }
100     }
101     for(int j = 1; (1 << j) <= n; j++) {
102         for(int i = 1; i <= n; i++) {
103             if(fa[i][j-1] != -1) {
104                 fa[i][j] = fa[fa[i][j-1]][j-1];
105             }
106         }
107     }
108 }
109 
110 int cal(int u, int v) {
111     if(deep[u] < deep[v]) swap(u, v);
112     int k;
113     for(k = 0; (1 << (1 + k)) <= deep[u]; k++);
114     for(int i = k; i >= 0; i--) {
115         if(deep[u] - (1 << i) >= deep[v]) {
116             u = fa[u][i];
117         }
118     }
119     if(u == v) return u;
120     for(int i = k; i >= 0; i--) {
121         if(fa[u][i] != -1 && fa[u][i] != fa[v][i]) {
122             u = fa[u][i];
123             v = fa[v][i];
124         }
125     }
126     return fa[u][0];
127 }
128 
129 int main() {
130 #ifndef ONLINE_JUDGE
131     FIN;
132 #endif
133     scanf("%d%d", &n, &q);
134     memset(head, -1, sizeof(head));
135     for(int i = 1; i <= n; i++) scanf("%d", &a[i]), v.push_back(a[i]);
136     sort(v.begin(), v.end());
137     v.erase(unique(v.begin(), v.end()), v.end());
138     len = v.size();
139     for(int i = 1; i < n; i++) scanf("%d%d", &x, &y), addedge(x, y);
140     dfs(1, 1, 0);
141     lca();
142     while(q--) {
143         scanf("%d%d%d", &x, &y, &k);
144         int p = cal(x, y);
145         printf("%d\n", v[query(1, len, root[x], root[y], root[p], root[fa[p][0]], k)-1]);
146     }
147     return 0;
148 }

 

posted @ 2018-09-28 16:44  Dillonh  阅读(359)  评论(0编辑  收藏  举报