CF763E Timofey and our friends animals
\(\tt Analysis\)
多次、区间、询问、问题不常规……考虑 莫队!
在莫队指针移动的途中,\(k\) 很小,因此边可以暴力加一个点的边。
至于联通块个数……这个并查集维护就行了。
并查集难以支持撤销(不然很难做到好的复杂度)。于是我们把莫队换成回滚莫队,然后就只需要普通并查集就行了。
\(\tt Details\)
莫队的回滚部分最后需要撤销所有并查集 fa 的改变。
因此这部分的并查集不能路径压缩,而前面的增部分可以路径压缩。
所以如果不写并查集按秩合并可能会挂(但是不知道为什么写了按秩合并比不写常数大一点)。
// C++20
const int N = 1e5 + 5,M = 5e5 + 5;
int n,k,m,q,B,bl[N],ans[N];
std::vector<int> E[N],P;
std::vector<std::tuple<int,int,int>> clr;
std::tuple<int,int,int> Q[M];
int fa[N],siz[N],cnt,p,r;
int fnd(int i){ return i == fa[i] ? i : fa[i] = fnd(fa[i]); }
int Fnd(int i){ return i == fa[i] ? i : Fnd(fa[i]); }
int main(){
scanf("%d%d%d",&n,&k,&m);
B = n / sqrt(m);
rep(i,1,n) bl[i] = (i - 1) / B + 1;
rep(i,1,m){
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}
scanf("%d",&q);
std::iota(fa + 1,fa + n + 1,1);
rep(i,1,q){
int l,r;
scanf("%d%d",&l,&r);
Q[i] = std::make_tuple(l,r,i);
if(bl[l] == bl[r]){
ans[i] = r - l + 1;
rep(u,l,r) for(int v : E[u])
if(l <= v && v < u){
int fu = fnd(u),fv = fnd(v);
if(fu == fv) continue;
fa[fu] = fv; --ans[i];
}
std::iota(fa + l,fa + r + 1,l);
}
}
auto cmp = [](auto a,auto b){
auto[l1,r1,i1] = a; auto[l2,r2,i2] = b;
return bl[l1] == bl[l2] ? r1 < r2 : l1 < l2;
};
std::sort(Q + 1,Q + q + 1,cmp);
rep(i,1,q){
auto[L,R,id] = Q[i];
auto[L_,R_,id_] = Q[i - 1];
if(bl[L] != bl[L_]){
p = r = ((bl[L] == bl[n]) ? n : bl[L] * B);
cnt = 0; std::iota(fa + 1,fa + n + 1,1);
}
if(bl[L] == bl[R]) continue;
while(r < R){
++cnt,++r;
for(int j : E[r])
if(p < j && j < r){
int fr = fnd(r),fj = fnd(j);
if(fr == fj) continue;
siz[fr] > siz[fj] ? fa[fj] = fr : fa[fr] = fj; --cnt;
}
}
int sum = p - L + 1;
Rep(l,p,L) for(int j : E[l])
if(l < j && j <= R){
int fl = Fnd(l),fj = Fnd(j);
if(fl == fj) continue;
clr.emplace_back(fj,fa[fj],siz[fj]);
clr.emplace_back(fl,fa[fl],siz[fl]);
siz[fl] > siz[fj] ? fa[fj] = fl : fa[fl] = fj; --sum;
}
ans[id] = sum + cnt;
std::ranges::reverse(clr);
for(auto[p,f,s] : clr) fa[p] = f,siz[p] = s;
clr.clear();
}
rep(i,1,q) printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号