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;
}
题意:给定一棵树,要求维护以下操作:
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;
}
相关文章推荐
- COGS-2258 复仇的序幕曲(动态树分治)
- BZOJ.3924.[ZJOI2015]幻想乡战略游戏(动态点分治)
- bzoj1901&zoj2112&cogs257 Dynamic Rankings(动态排名系统)
- bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)
- bzoj3295 [Cqoi2011]动态逆序对(CDQ分治)
- 动态规划入门 COGS1398 最长上升子序列
- [动态MST] [CDQ分治] BZOJ2001: [Hnoi2010]City 城市建设
- 【BZOJ-3730】震波 动态点分治 + 树状数组
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 【动态点分治 + 堆】
- 洛谷P1393 动态逆序对(CDQ分治)
- bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)
- bzoj 1095: [ZJOI2007]Hide 捉迷藏 (动态点分治)
- 【HDU】5571 tree【动态点分治】
- 2016.4.06Test:problem1:异或树:动态树的点分治
- 洛谷3345:幻想乡战略游戏(动态树分治)
- bzoj 3295: [Cqoi2011]动态逆序对 【cdq分治】
- COGS 577 蝗灾 [CDQ分治入门题]
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
- 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)
- [BZOJ3924][Zjoi2015]幻想乡战略游戏(动态点分治)