(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小)

P4216 [SCOI2015]情报传递 LCA+树上主席树 离线操作

P4216 [SCOI2015]情报传递 LCA+树上主席树 离线操作