[ABC219G] Propagation
学校断网 VP 的时候 A 的,于是决定来写一篇题解。
很容易就可以想到根号分治。至于为什么可以想到,引用某大佬的话“啪的一下就想到根号分治,很快啊”。
以下简称与节点
当你发现:大小超过
所以,当点
当要更新该节点时,只需要搜索与它直接相连的节点中大小不超过
以上操作均为更号级别。
时间复杂度:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
const int hal=450;
vector<vector<int>> G(N);
vector<vector<int>> nxt(N);
int a[N];
int col[N],tim[N],tim1[N];
signed main()
{
int n,m,q;cin>>n>>m>>q;
for(int i=1;i<=n;i++) a[i]=i;
for(int i=1;i<=m;i++){
int u,v;cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=1;i<=n;i++){
if(G[i].size()<hal) continue;
for(auto it:G[i]) nxt[it].push_back(i);
}
for(int i=1;i<=q;i++)
{
int dir;cin>>dir;
int cnt=0,maxn=0;
for(auto it:nxt[dir]) {
if(tim1[it]>maxn&&tim1[it]>tim[dir]){
maxn=tim1[it];
cnt=col[it];
}
}
if(cnt!=0) a[dir]=cnt,tim[dir]=maxn;
if(G[dir].size()<hal) for(auto it:G[dir]) a[it]=a[dir],tim[it]=i;
else {
col[dir]=a[dir];
tim1[dir]=i;
}
}
for(int i=1;i<=n;i++) {
int cnt=0,maxn=0;
for(auto it:nxt[i]) {
if(tim1[it]>maxn&&tim1[it]>tim[i]){
maxn=tim1[it];
cnt=col[it];
}
}
if(cnt!=0) a[i]=cnt,tim[i]=maxn;
cout<<a[i]<<" ";
}
}