(LCA+树上主席树)FZU 2237 - 中位数
Posted tak_fate
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(LCA+树上主席树)FZU 2237 - 中位数相关的知识,希望对你有一定的参考价值。
题意:
多次查询一个树链上的中位数(其实就是求K大)。
分析:
感觉莫队可做,只是不会树上莫队。。
而且这里是边权,处理起来貌似有点小麻烦。。
后来发现其实貌似是一个很老的题,,kuangbin模板书上有类似的题。
树链上的第K大数,这是一道可以用主席树解的题,复杂度才nlogn。
这里也是这样先求从根到每个点的线段树,以为树存在父子关系,所有可以从让下层继承上层的线段树,非常符合主席树的可持久化思想。
然后在查询第K大的时候,去掉重复部分,就可以查了。
太强了,,,
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <set> 7 #include <vector> 8 #include <queue> 9 #include <map> 10 #include <list> 11 #include <bitset> 12 #include <string> 13 #include <cctype> 14 #include <cstdlib> 15 16 using namespace std; 17 18 typedef long long ll; 19 typedef unsigned long long ull; 20 #define inf (0x3f3f3f3f) 21 #define lnf (0x3f3f3f3f3f3f3f3f) 22 #define eps (1e-8) 23 int sgn(double a) { 24 return a < -eps ? -1 : a < eps ? 0 : 1; 25 } 26 27 int n, q; 28 const int maxn = 50010; 29 const int m = 100001; 30 struct Node { 31 int v, c; 32 }; 33 34 vector<Node> g[maxn]; 35 const int DEG = 16; 36 int fa[maxn][DEG]; 37 int deg[maxn]; 38 39 void addedge(int u, int v, int w) { 40 Node a, b; 41 a.v = v; 42 a.c = w; 43 b.v = u; 44 b.c = w; 45 g[u].push_back(a); 46 g[v].push_back(b); 47 } 48 49 void bfs(int root) { 50 queue<int> q; 51 deg[root] = 0; 52 fa[root][0] = root; 53 q.push(root); 54 while(!q.empty()) { 55 int tmp = q.front(); 56 q.pop(); 57 for(int i = 1; i < DEG; i++) { 58 fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1]; 59 } 60 for(int i = 0; i < (int)g[tmp].size(); i++) { 61 int v = g[tmp][i].v; 62 if(v == fa[tmp][0])continue; 63 deg[v] = deg[tmp] + 1; 64 fa[v][0] = tmp; 65 q.push(v); 66 } 67 } 68 } 69 70 int LCA(int u, int v) { 71 if(deg[u] > deg[v])swap(u, v); 72 for(int det = deg[v] - deg[u], i = 0; det; det >>= 1, i++) { 73 if(det & 1)v = fa[v][i]; 74 } 75 if(u == v)return u; 76 for(int i = DEG - 1; i >= 0; i--) { 77 if(fa[u][i] != fa[v][i]) { 78 u = fa[u][i]; 79 v = fa[v][i]; 80 } 81 } 82 return fa[u][0]; 83 } 84 85 86 87 88 int T[maxn], lson[maxn * 30], rson[maxn * 30]; 89 int c[maxn * 30]; 90 int tot = 0; 91 92 int build(int l, int r) { 93 int root = tot++; 94 c[root] = 0; 95 if(l != r) { 96 int mid = (l + r) >> 1; 97 lson[root] = build(l, mid); 98 rson[root] = build(mid + 1, r); 99 } 100 return root; 101 } 102 103 104 int update(int root, int pos, int val) { 105 int newroot = tot++, tmp = newroot; 106 c[newroot] = c[root] + val; 107 int l = 1, r = m; 108 while(l < r) { 109 int mid = (l + r) >> 1; 110 if(pos <= mid) { 111 lson[newroot] = tot++; 112 rson[newroot] = rson[root]; 113 newroot = lson[newroot]; 114 root = lson[root]; 115 r = mid; 116 } else { 117 rson[newroot] = tot++; 118 lson[newroot] = lson[root]; 119 newroot = rson[newroot]; 120 root = rson[root]; 121 l = mid + 1; 122 } 123 c[newroot] = c[root] + val; 124 } 125 return tmp; 126 } 127 128 int query(int u_root, int v_root, int fa_root, int k) { 129 int l = 1, r = m; 130 while(l < r) { 131 int mid = (l + r) >> 1; 132 if(c[lson[u_root]] + c[lson[v_root]] - 2 * c[lson[fa_root]] >= k) { 133 r = mid; 134 u_root = lson[u_root]; 135 v_root = lson[v_root]; 136 fa_root = lson[fa_root]; 137 } else { 138 l = mid + 1; 139 k -= c[lson[u_root]] + c[lson[v_root]] - 2 * c[lson[fa_root]]; 140 u_root = rson[u_root]; 141 v_root = rson[v_root]; 142 fa_root = rson[fa_root]; 143 } 144 } 145 return l; 146 } 147 148 149 150 void dfs(int u, int par, int val) { 151 T[u] = update(T[par], val, 1); 152 for(int i = 0; i < (int)g[u].size(); i++) { 153 int v = g[u][i].v; 154 if(v == par)continue; 155 dfs(v, u, g[u][i].c); 156 } 157 } 158 159 160 void init() { 161 for(int i = 1; i <= n; i++) { 162 g[i].clear(); 163 } 164 tot = 0; 165 memset(fa, 0, sizeof(fa)); 166 } 167 168 void solve() { 169 while(~scanf("%d%d", &n, &q)) { 170 init(); 171 for(int i = 0; i < n - 1; i++) { 172 int u, v, w; 173 scanf("%d%d%d", &u, &v, &w); 174 w++; 175 addedge(u, v, w); 176 177 } 178 bfs(1); 179 T[0] = build(1, m); 180 dfs(1, 0, 1); 181 while(q--) { 182 int u, v; 183 scanf("%d%d", &u, &v); 184 int fa = LCA(u, v); 185 int k = (c[T[u]] + c[T[v]] - 2 * c[T[fa]] + 1) / 2; 186 printf("%d\n", query(T[u], T[v], T[fa], k) - 1); 187 } 188 189 } 190 191 } 192 193 194 195 int main() { 196 197 #ifndef ONLINE_JUDGE 198 // freopen("1.in", "r", stdin); 199 //freopen("1.out", "w", stdout); 200 #endif 201 //iostream::sync_with_stdio(false); 202 solve(); 203 return 0; 204 }
以上是关于(LCA+树上主席树)FZU 2237 - 中位数的主要内容,如果未能解决你的问题,请参考以下文章
UVALive - 7831 :ACM Tax (主席树求树路径上中位数:LCA+主席树)
spoj COT - Count on a tree (树上第K小 LCA+主席树)
BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树
SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)