小a与军团模拟器
题目描述
9102
年伊始,小a觉得山羊模拟器,乞丐模拟器之类的都太低级了,所以想自己建立一个征战天下的军团模拟器。
军团模拟器是在一个城市数为N的国家中运行的,每个城市都会通过一些道路和其他所有城市相连,道路总数为N−1。 开始时,每个城市中都会有一个军队,每个军队有着自己的编号。
定义军团为相邻的同种编号军队的最大联通块,有些时候某种编号的军队会改变自己的编号,小a想要知道这些时候整个国家有多少军团。 形式化的,我们会有Q次操作,每次操作为以下形式
一行两个正整数a,b表示所有编号为a的军队编号变成b
输入描述:
第一行两个整数N,Q
接下来一行N
个非负整数,表示初始时N
个城市上军队的编号是多少,如果为0
那么无军队。
接下来N−1
行每行两个正整数u,v
表示城市u
和城市v
之间有道路相连。
接下来Q
行,两个整数x,y
表示询问操作。
输出描述:
对于每次询问,输出一行一个整数,表示询问过后的军团数。
示例1
操作一使得3号节点的编号由3改为2,此时仍有四个军团
操作二使得4,5号节点的编号由2改为1,此时只有一个军团
示例2
输入
5 6 1 2 3 4 9 1 2 2 3 3 4 4 5 1 2 2 1 2 3 1 3 3 4 4 5
输出
4 4 4 3 2 2
备注:
保证1⩽N,Q,所有编号最大值⩽200000
保证输入数据合法
思路:启发式合并
暴力做法是存一下每一种颜色对应的节点,然后统计一下和它相邻的颜色不同的节点个数并减去,修改之后再统计一遍相邻的不同颜色的节点个数,再加上。
如果把节点很多的修改成很少的,这样还是会炸。
考虑启发式合并,把颜色少的并到多的上,再用一个数组映射一下该颜色对应的是什么颜色就行了
我不会复杂度分析。
题解原话:每个点的复杂度是他的度数乘以它被统计答案的次数,最差情况下每个点也只会被统计logN次答案,最终复杂度为O(𝑁𝑙𝑜𝑔𝑁)
#include <bits/stdc++.h> #define pb push_back using namespace std; template<typename T> inline void read(T &x) { x = 0;T f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); } x *= f; } const int N = 2e5 + 10; int n, col[N], ans, mp[N]; vector<int> color[N], G[N]; void dfs(int u, int fa) { for (auto v: G[u]) { if (v == fa) continue; if (col[v] && col[v] != col[u]) ans++; dfs(v, u); } } void solve(int &x, int &y) { if (color[x].size() > color[y].size()) swap(x, y); for (auto u: color[x]) for (auto v: G[u]) { if (col[v] && col[v] != x) ans--; } for (auto u: color[x]) { col[u] = y; color[y].pb(u); } for (auto u: color[x]) for (auto v: G[u]) if (col[v] && col[v] != y) ans++; color[x].clear(); x = -1; } int main() { int q; read(n); read(q); for (int i = 1; i <= n; i++) read(col[i]), color[col[i]].pb(i), mp[i] = i; for (int i = 1; i < n; i++) { int u, v; read(u), read(v); G[u].pb(v); G[v].pb(u); } if (col[1] != 0) ans++; dfs(1, 1); while (q--) { int x, y; read(x), read(y); if (mp[y] < 0) mp[x] = -1, mp[y] = x; else if (mp[x] >= 0 && mp[x] != mp[y]) solve(mp[x], mp[y]); printf("%d\n", ans); } return 0; }

浙公网安备 33010602011771号