LCA 练习总结

LCA 资料: http://www.cnblogs.com/zgmf_x20a/archive/2008/10/15/1311313.html

虽然网上这方面资料很多了, 不过自己练习后还是写下。。。

POJ 1330 Nearest Common Ancestors

输入N-1条边,建一个树,然后是一个LCA查询,只有一次,朴素做比较快。

树是唯一的。

POJ 1470 Closest Common Ancestors

和上一题非常类似,不过点变少了,查询次数变多了,因为n<=900朴素就可以了。

POJ 1986 Distance Queries

查询从u-v的距离。

根据输入建一个树,以任意点位根都可以,距离是不变的。

然后每个节点保存到根的距离dis[],这样结果可以就是

dis[u] + dis[v] - 2 * dis[lca(u, v)]; 去掉重复的与无用的。。

POJ 3728 The merchant

给出n个点买入与卖出商品的价格,然后给出n-1条边。 问: 

u-v上进行一次交易,可以选一个在u-v之间的点买入,然后再这个点之后的点卖出,的最大获益,既买入价格-卖出价格。

可以考虑这么做:

求出lca(u, v), 这样问题可以分解为u - lca(u, v)的最大获益, lca(u, v)的最大获益,以及u - lca(u, v)的最大值 - lca(u, v) - v的最小值, 中的最大值。

可以用类似求lcaDP求出最大值、最小值,最大获益,最小获益(考虑方向)

POJ 3237 Tree

题意:

CHANGE i v Change the weight of the ith edge to v

NEGATE a b Negate the weight of every edge on the path from a to b

QUERY a b Find the maximum weight of edges on the path from a to b

很清楚了。。

没有什么特别的想法,但数据比较水,直接log(n)lca(u,v)然后修改所有

u - lca(u,v), v - lca(u, v)就可以水过去...

POJ 2763 Housewife Wind

在搜索的时候记录点第一次出现位置LT[],与结束位置RT[],这样对u - v边得修改, 影响的值是LT[u] - RT[u], 区间问题, 可以用树状数组解决。

因为dis[u] + dis[v] - 2 * dis[lca(u, v)]所以这里只有修改V[LT[u]] + change

和 V[RT[u] + 1] - change,就可以了。 最后查询是的结果是sum(LT[u]) + sum(LT[v]) - 2 * sum(LT[lca(u, v)]); 注意这里修改的是change, 与输出的v有区别的。 初始化可以当做是从0-vchange, 同样处理就可以了。 不过开10W一直RE, 改20WAC了。。。。

POJ 3368 Frequent values

RMQ做的,没线段树有效率。因为输入有序的,可以考虑把点合并成个数与值,

然后查询就变成查cnt最大的的RMQ问题了, 注意出发点,与结束点的区间分解。

ZOJ 3195 Design the city

和POJ 1986 Distance Queries类似, 变成三个点的距离了。

结果是 (dis[a] - dis[ab] + dis[a] - dis[ac] +

        dis[b] - dis[ab] + dis[b] - dis[bc] +

        dis[c] - dis[ac] + dis[c] - dis[bc]) / 2;

HDU 2586 How far away

和POJ 1986 Distance Queries一样。。。

View Code
1 //vector 会超时
2 const int MAXN = 200200;
3 const int MAXNLOG = 20;
4 struct Node {
5 int first;
6 int second;
7 }g[MAXN<<1];
8 int nxt[MAXN], head[MAXN], ne;
9 int dep[MAXN];
10 int pa[MAXN][MAXNLOG], dis[MAXN];
11 int LT[MAXN], RT[MAXN], id;
12
13 inline void addedge(int u, int v, int w) {
14 g[ne].first = v, g[ne].second = w;
15 nxt[ne] = head[u]; head[u] = ne++;
16 g[ne].first = u, g[ne].second = w;
17 nxt[ne] = head[v]; head[v] = ne++;
18 }
19
20 void dfs(int u, int fa, int d, int v) {
21 dis[u] = v, dep[u] = d, pa[u][0] = fa;
22 LT[u] = id++;
23 for (int i = head[u]; i != -1; i = nxt[i]) {
24 if (g[i].first != fa) {
25 dfs(g[i].first, u, d + 1, v + g[i].second);
26 }
27 }
28 RT[u] = id;
29 }
30
31 void process(int n) {
32 for (int i = 0; i < n; ++i) {
33 for (int j = 0; (1 << j) < n; ++j) {
34 pa[i][j] = -1;
35 }
36 }
37 id = 1;
38 dfs(0, 0, 0, 0);
39 for (int j = 1; (1 << j) < n; ++j) {
40 for (int i = 0; i < n; ++i) {
41 if (pa[i][j-1] != -1) {
42 pa[i][j] = pa[pa[i][j-1]][j-1];
43 }
44 }
45 }
46 }
47
48 int lca(int a, int b) {
49 if (dep[a] < dep[b]) {
50 swap(a, b);
51 }
52 int tmp = 1;
53 for (; (1 << tmp) <= dep[a]; ++tmp);
54 --tmp;
55 for (int i = tmp; i >= 0; --i) {
56 if (dep[a] - (1 << i) >= dep[b]) {
57 a = pa[a][i];
58 }
59 }
60 if (a == b) {
61 return a;
62 }
63 for (int i = tmp; i >= 0; --i) {
64 if (pa[a][i] != -1 && pa[a][i] != pa[b][i]) {
65 a = pa[a][i], b = pa[b][i];
66 }
67 }
68 return pa[a][0];
69 }
70
71 int n, dfn[MAXN];
72 int road[MAXN][3];
73 inline void add(int x, int v) {
74 while (x <= n) {
75 dfn[x] += v;
76 x += x & -x;
77 }
78 }
79
80 inline int sum(int x) {
81 int ret = 0;
82 while (x > 0) {
83 ret += dfn[x];
84 x -= x & -x;
85 }
86 return ret;
87 }
88
89 int main () {
90 while (true) {
91 n = nextInt();
92 int q = nextInt();
93 int s = nextInt() - 1;
94 ne = 0, memset(head, -1, sizeof(head));
95 //g.clear(); g.resize(n);
96 for (int i = 0; i < n - 1; ++i) {
97 int a = nextInt() - 1;
98 int b = nextInt() - 1;
99 int w = nextInt();
100 addedge(a, b, w);
101 //g[a].push_back(MP(b, w));
102 //g[b].push_back(MP(a, w));
103 road[i][0] = a, road[i][1] = b, road[i][2] = w;
104 }
105 process(n);
106 while (q--) {
107 int ope = nextInt();
108 if (ope == 0) {
109 int v = nextInt() - 1;
110 int l = lca(s, v);
111 int d = dis[s] + dis[v] - 2 * dis[l];
112 d += sum(LT[s]) + sum(LT[v]) - 2 * sum(LT[l]);
113 printf("%d\n", d);
114 s = v;
115 }
116 else {
117 int x = nextInt() - 1;
118 int v = nextInt();
119 int index = road[x][0];
120 if (dep[index] < dep[road[x][1]]) {
121 index = road[x][1];
122 }
123 int c = v - road[x][2];
124 road[x][2] = v;
125 add(LT[index], c);
126 add(RT[index], -c);
127 }
128 }
129 }
130 return 0;
131 }

posted on 2011-06-13 16:46  cegr  阅读(1207)  评论(2编辑  收藏  举报