BJOI2014 大融合
Posted dmoransky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BJOI2014 大融合相关的知识,希望对你有一定的参考价值。
Description
给定 (n) 个点,要求支持操作:
- 连接 ((x, y)) 这条边
- 求当前状态下经过 ((x, y)) 这条边的路径数量
Solution
考虑这题可以离线,先把树的结构建出来。
考虑动态维护每个节点的子树大小 (size_i) 与当前联通快的根节点 (root_i)。
- 对于连接操作,设在我们建的结构中 (x) 为 (y) 的父亲(否则 ( ext{swap})),链接这条边,相当于将 (x Rightarrow root_x) 这条链上的 (size) 都 (+ size_y),即一个链加操作。然后将 (y) 联通块的 (root) 都赋值为 (root_x)。
- 对于查询操作,同样设在我们建的结构中 (x) 为 (y) 的父亲(否则 ( ext{swap})),答案即为 (size_{y} * (size_{root_x} - size_{y}))。
对于 (root) 的维护,用并查集即可,做到 (O(Nlog_2N))
对于 (size) 的维护,可以暴力树链剖分,也可以差分 (+) 树状数组(详情看 Loj #146. DFS 序 3,树上差分 1),我用了后者 (O(Nlog_2N))。
时间复杂度
(O(N log_2N))
Code
#include <iostream>
#include <cstdio>
const int N = 100005;
using namespace std;
typedef long long LL;
int n, m, rt[N], sz[N], dfn[N], dfncnt, fa[N];
int opt[N], A[N], B[N], c[N];
int head[N], numE = 0;
struct E {
int next, v;
} e[N << 1];
inline void addEdge(int u, int v) {
e[++numE] = (E){ head[u], v };
head[u] = numE;
}
int find(int x) { return rt[x] == x ? x : rt[x] = find(rt[x]); }
void inline add(int x, int k) {
if (x == 0)
return;
for (; x <= n; x += x & -x) c[x] += k;
}
int inline ask(int x) {
int res = 0;
for (; x; x -= x & -x) res += c[x];
return res;
}
void dfs(int u) {
dfn[u] = ++dfncnt, sz[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if (v == fa[u])
continue;
fa[v] = u;
dfs(v);
sz[u] += sz[v];
}
}
int inline query(int x) { return ask(dfn[x] + sz[x] - 1) - ask(dfn[x] - 1) + 1; }
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) rt[i] = i;
for (int i = 1; i <= m; i++) {
char c[2];
scanf("%s%d%d", c, A + i, B + i);
opt[i] = c[0] == ‘A‘ ? 0 : 1;
if (!opt[i])
addEdge(A[i], B[i]), addEdge(B[i], A[i]);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
dfs(i);
for (int i = 1; i <= m; i++) {
int x = A[i], y = B[i];
if (y == fa[x])
swap(x, y);
if (opt[i] == 0) {
// 连接
rt[find(y)] = find(x);
x = find(x);
int v = query(y);
add(dfn[fa[x]], -v), add(dfn[fa[y]], v);
} else {
// 查询
x = find(x);
printf("%lld
", (LL)query(y) * (query(x) - query(y)));
}
}
return 0;
}
以上是关于BJOI2014 大融合的主要内容,如果未能解决你的问题,请参考以下文章