树链剖分

Posted Milky Way

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树链剖分相关的知识,希望对你有一定的参考价值。

bzoj 3531 [Sdoi2014]旅行

题意:维护一棵树,每个结点都有一个种类和一个权值,支持单点修改种类或权值、询问链上某一种类的权值和或最大值

思路:开 c 棵线段树,每一棵代表一个宗教,然后树剖

技术分享图片
  1 #include <cstdio>
  2 #include <string>
  3 #include <vector>
  4 
  5 const int N = 1e5 + 10;
  6 
  7 int dfs_clock;
  8 
  9 struct Edge{
 10     int to;
 11 };
 12 std::vector<Edge> edges;
 13 std::vector<int> G[N];
 14 
 15 struct Node {
 16     int size, deep, pos, top, fa, son, w, c;
 17 } a[N];
 18 
 19 int max(int x, int y) {
 20     if (x >= y) return x;
 21     return y;
 22 }
 23 
 24 void swap(int &x, int & y) {
 25     x ^= y, y ^= x, x ^= y;
 26 }
 27 
 28 void AddEdge(int from, int to) {
 29     G[from].push_back(edges.size());
 30     edges.push_back((Edge){to});
 31 }
 32 
 33 int read() {
 34     int x = 0, f = 1;
 35     char c = getchar();
 36     while (!isdigit(c)) {
 37         if (c == -) f = -1;
 38         c = getchar();
 39     }
 40     while (isdigit(c)) {
 41         x = (x << 3) + (x << 1) + (c ^ 48);
 42         c = getchar();
 43     }
 44     return x * f;
 45 }
 46 
 47 struct segtree {
 48     segtree *ls, *rs;
 49     int sum, mx;
 50     void maintain() {
 51         sum = mx = 0;
 52         if (ls != NULL) {
 53             sum += ls->sum;
 54             mx = max(mx, ls->mx);
 55         }
 56         if (rs != NULL) {
 57             sum += rs->sum;
 58             mx = max(mx, rs->mx);
 59         }
 60     }
 61     segtree() {ls = rs = NULL, sum = mx = 0;}
 62 } *tree[N];
 63 
 64 typedef segtree sgt;
 65 
 66 void dfs1(int cur, int father, int depth) {
 67     a[cur].size = 1, a[cur].deep = depth, a[cur].fa = father, a[cur].son = 0;
 68     int size = G[cur].size();
 69     for (int i = 0; i < size; ++ i) {
 70         int nx = edges[G[cur][i]].to;
 71         if (nx != father) {
 72             dfs1(nx, cur, depth + 1);
 73             a[cur].size += a[nx].size;
 74             if (a[nx].size > a[a[cur].son].size)
 75                 a[cur].son = nx;
 76         }
 77     }
 78 }
 79 
 80 void dfs2(int cur, int top) {
 81     a[cur].top = top, a[cur].pos = ++dfs_clock;
 82     if (a[cur].son) dfs2(a[cur].son, top);
 83     int size = G[cur].size();
 84     for (int i = 0; i < size; ++ i) {
 85         int nx = edges[G[cur][i]].to;
 86         if (nx != a[cur].fa && nx != a[cur].son)
 87             dfs2(nx, nx);
 88     }
 89 }
 90 
 91 void insert(sgt* &cur, int l, int r, int pos, int val) {
 92     if (cur == NULL) cur = new segtree();
 93     if (l == r) {
 94         cur->sum = cur->mx = val;
 95         return;
 96     }
 97     int mid = l + ((r - l) >> 1);
 98     if (pos <= mid) insert(cur->ls, l, mid, pos, val);
 99     else insert(cur->rs, mid + 1, r, pos, val);
100     cur -> maintain();
101 }
102 
103 void erase(sgt* &cur, int l, int r, int pos) {
104     if (cur == NULL) return;
105     if (l == r) {
106         delete cur; cur = NULL;
107         return;
108     }
109     int mid = l + ((r - l) >> 1);
110     if (pos <= mid) erase(cur->ls, l, mid, pos);
111     else erase(cur->rs, mid + 1, r, pos);
112     if (cur->ls == NULL && cur->rs == NULL) {
113         delete cur; cur = NULL;
114     } else {
115         cur -> maintain();
116     }
117 }
118 
119 int Q_max(sgt* &cur, int l, int r, int L, int R) {
120     if (cur == NULL) return 0;
121     if (L <= l && r <= R) return cur->mx;
122     int mid = l + ((r - l) >> 1), ans = 0;
123     if (L <= mid) ans = max(ans, Q_max(cur->ls, l, mid, L, R));
124     if (mid < R) ans = max(ans, Q_max(cur->rs, mid + 1, r, L, R));
125     return ans;
126 }
127 
128 int Q_sum(sgt* &cur, int l, int r, int L, int R) {
129     if (cur == NULL) return 0;
130     if (L <= l && r <= R) return cur->sum;
131     int mid = l + ((r - l) >> 1), ans = 0;
132     if (L <= mid) ans += Q_sum(cur->ls, l, mid, L, R);
133     if (mid < R) ans += Q_sum(cur->rs, mid + 1, r, L, R);
134     return ans;
135 }
136 
137 int chain_max(sgt* &cur, int x, int y) {
138     int ans = 0;
139     while (a[x].top != a[y].top) {
140         if (a[a[x].top].deep < a[a[y].top].deep) swap(x, y);
141         ans = max(ans, Q_max(cur, 1, dfs_clock, a[a[x].top].pos, a[x].pos));
142         x = a[a[x].top].fa;
143     }
144     if (a[x].deep > a[y].deep) swap(x, y);
145     ans = max(ans, Q_max(cur, 1, dfs_clock, a[x].pos, a[y].pos));
146     return ans;
147 }
148 
149 int chain_sum(sgt* &cur, int x, int y) {
150     int ans = 0;
151     while (a[x].top != a[y].top) {
152         if (a[a[x].top].deep < a[a[y].top].deep) swap(x, y);
153         ans += Q_sum(cur, 1, dfs_clock, a[a[x].top].pos, a[x].pos);
154         x = a[a[x].top].fa;
155     }
156     if (a[x].deep > a[y].deep) swap(x, y);
157     ans += Q_sum(cur, 1, dfs_clock, a[x].pos, a[y].pos);
158     return ans;
159 }
160 
161 int main() {
162     int n = read(), m = read();
163     for (int i = 1; i <= n; ++ i) {
164         a[i].w = read(), a[i].c = read();
165     }
166     for (int i = 1; i < n; ++ i) {
167         int u = read(), v = read();
168         AddEdge(u, v); AddEdge(v, u);
169     }
170     dfs1(1, 0, 1); dfs2(1, 1);
171     for (int i = 1; i <= n; ++ i) {
172         insert(tree[a[i].c], 1, n, a[i].pos, a[i].w);
173     }
174     while (m --) {
175         char op = getchar(), t = getchar();
176         int x = read(), y = read();
177         if (op == C) {
178             if (t == C) {
179                 erase(tree[a[x].c], 1, n, a[x].pos);
180                 insert(tree[y], 1, n, a[x].pos, a[x].w);
181                 a[x].c = y;
182             } else {
183                 insert(tree[a[x].c], 1, n, a[x].pos, y);
184                 a[x].w = y;
185             }
186         } else {
187             if (t == S) {
188                 printf("%d\n", chain_sum(tree[a[x].c], x, y));
189             } else {
190                 printf("%d\n", chain_max(tree[a[x].c], x, y));
191             }
192         }
193     }
194     return 0;
195 }
View Code

bzoj 3083 遥远的国度

题意:维护一棵树,支持换根、树链覆盖、查询子树最小值

思路:仅当根节点在某个询问的子树上时才对答案有影响:若询问的结点为根,则查询子树;若询问结点为根的祖先,则查询该节点离根最近的儿子的子树的补集

以上是关于树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

树链剖分小结

树链剖分详解

树链剖分

树链剖分 入门

树链剖分

树链剖分(轻/重链剖分学习笔记)