您的位置:首页 > 其它

COGS-2278 树黑白(动态树分治)

2017-08-14 20:48 399 查看
传送门:COGS-2278

题意:给定一棵树,要求维护以下操作:

1、M u 将u节点反色

2、Q u 查询u到所有黑色节点距离和

题解:动态树分治,更新时判断一下原本是黑色还是白色,是黑色就减去u与根的距离,是白色就加上

#include<bits/stdc++.h>
using namespace std;
const int MX = 2e5 + 5;
const int MXM = MX * 40;
struct Edge {
int v, w, nxt;
} E[MX * 2];
struct Root {
int rt, subrt, dis, nxt;
} root[MXM];
int head[MX], fir[MX];
int c[MX], vis[MX], sz[MX], id[MX];
int sum[MX << 1], num[MX << 1];
int n, m, tot, cnt, rear;
void init() {
memset(head, -1, sizeof(head));
memset(fir, -1, sizeof(fir));
tot = cnt = rear = 0;
}
void add_edge(int u, int v, int w) {
E[tot].v = v;
E[tot].w = w;
E[tot].nxt = head[u];
head[u] = tot++;
}
void add_root(int u, int rt, int subrt, int dis) {
root[rear].rt = rt;
root[rear].subrt = subrt;
root[rear].dis = dis;
root[rear].nxt = fir[u];
fir[u] = rear++;
}
void dfs_size(int u, int fa, int tot, int &rt) {
sz[u] = 1;
for (int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v] || v == fa) continue;
dfs_size(v, u, tot, rt);
sz[u] += sz[v];
}
if (!rt && sz[u] * 2 > tot) rt = u;
}
void dfs_tree(int u, int fa, int rt, int subrt, int dir) {
add_root(u, rt, subrt, dir);
for (int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v] || v == fa) continue;
dfs_tree(v, u, rt, subrt, dir + E[i].w);
}
}
void dfs(int u) {
int rt = 0; dfs_size(u, 0, 0, rt);
dfs_size(u, 0, sz[u], rt = 0);
vis[rt] = 1; id[rt] = ++cnt;
add_root(rt, id[rt], 0, 0);
for (int i = head[rt]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v]) continue;
dfs_tree(v, rt, id[rt], ++cnt, E[i].w);
}
for (int i = head[rt]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v]) continue;
dfs(v);
}
}
int query(int u) {
int ret = 0;
for (int i = fir[u]; ~i; i = root[i].nxt) {
int rt = root[i].rt, subrt = root[i].subrt, dis = root[i].dis;
ret += sum[rt] + num[rt] * dis - sum[subrt] - num[subrt] * dis;
}
return ret;
}
void update(int u) {
int t = c[u] ? -1 : 1;
for (int i = fir[u]; ~i; i = root[i].nxt) {
int rt = root[i].rt, subrt = root[i].subrt, dis = root[i].dis;
sum[rt] += dis * t;
num[rt] += t;
if (subrt) sum[subrt] += dis * t, num[subrt] += t;
}
c[u] ^= 1;
}
int main() {
freopen("A_Tree.in", "r", stdin);
freopen("A_Tree.out", "w+", stdout);
scanf("%d%d", &n, &m);
init();
for (int i = 1, u, v, w; i < n; i++) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w); add_edge(v, u, w);
}
dfs(1);
char op[2];
for (int i = 1, u; i <= m; i++) {
scanf("%s%d", op, &u);
if (op[0] == 'M') update(u);
else printf("%d\n", query(u));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: