ABC219 G - Propagation(图分块)
目录
Description
有一个图有 \(n\) 个节点,\(m\) 条边,每个点由它对应的编号和权值,初始时权值为编号,有 \(Q\) 次操作,可以将与 \(x\) 节点相连的所有节点的权值变为 \(x\) 节点的权值,求最后所有节点的权值
State
\(1<=n<=2*10^5\)
\(0<=m<=min(2*10^5,\frac{n(n-1)}{2})\)
\(1<=Q<=2*10^5\)
\(1<=u_i<=v_i<=n\)
\(1<=x_i<=n\)
Input
5 6 3
4 2
4 3
1 2
2 3
4 5
1 5
1 3 4
Output
1 3 3 3 3
Solution
如果每一次更新去暴力求解,时间复杂度为 \(O(Q*m)\)
很容易看出时间复杂度与每个节点的度有关,这时就需要利用图分块将度比较大的节点延迟处理
根据套路,如果节点 \(u\) 连接的一个节点 \(v\) 的度过大,那么将这个节点 \(v\) 作为与 \(u\) 相连接的节点
对于每次操作 \(x\), 如果 \(x\) 的度过大,那么只更改其延迟标记 \(lazy\) 即可;
否则将其所连接的节点暴力修改即可。
当前 \(x\) 节点的答案为其所连重点的 \(lazy\) 之一(可以不包含当前 \(x\) 节点的 \(lazy\))
Code
const int N = 2e5 + 5;
int n, m, k, _;
vector<int> G[N], G2[N];
int block;
pii ans[N], lag[N];
signed main()
{
// IOS;
int Q;
while(~ sddd(n, m, Q)){
int x, y;
rep(i, 1, m){
sdd(x, y);
G[x].pb(y);
G[y].pb(x);
}
block = sqrt(m);
for(int i = 1; i <= n; i ++){
for(int j = 0; j < G[i].size(); j ++){
x = G[i][j];
if(G[x].size() > block) G2[i].pb(x);
}
}
for(int i = 1; i <= n;i ++) ans[i] = lag[i] = {i, 0};
for(int k = 1; k <= Q; k ++){
sd(x);
for(auto it : G2[x]){
if(lag[it].se > ans[x].se){
ans[x] = lag[it];
}
}
if(G[x].size() <= block){
for(auto it : G[x]){
ans[it] = {ans[x].fi, k};
}
}
else{
// lag[x] = {ans[x].fi, k}; 同样 AC
ans[x] = lag[x] = {ans[x].fi, k};
}
}
for(int i = 1; i <= n; i ++){
for(auto it : G2[i]){
if(lag[it].se > ans[i].se){
ans[i] = lag[it];
}
}
printf("%d ", ans[i].fi);
}
puts("");
}
// PAUSE;
return 0;
}

浙公网安备 33010602011771号