题目链接: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("********* "); 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 ", v[query(1, len, root[x], root[y], root[p], root[fa[p][0]], k)-1]); 146 } 147 return 0; 148 }