P11369 [Ynoi2024] 弥留之国的爱丽丝 / 定期重构
题目传送门:P11369 [Ynoi2024] 弥留之国的爱丽丝。
假设 \(n,m,q\) 同阶。
首先这个不弱于 DAG 联通性,考虑使用 \(\frac{1}{\omega}\) 做法。
首先我们将操作按照 \(B\) 分块,对于每一块,定义关键点为操作和询问涉及的点,关键边为操作涉及的边,那么显然关键点边个数均为 \(O(B)\) 量级。
考虑建出一个图 \(G_1\) 包含所有点和非关键且黑色的边,那么就可以直接缩点利用 bitset 维护出连通性。
然后建出一个图 \(G_2\) 包含所有关键点,如果关键点在 \(G_1\) 联通,那么这里连一条边,直接利用 bitset 存邻接矩阵。
然后建出一个图 \(G_3\) 动态维护所有关键边的状态,黑色在图中,白色不在图中,也可以利用 bitset 存,注意这里维护需要考虑一下重边。
然后依次处理所有询问,动态维护 \(G_3\),然后直接在 \(G_2\) 和 \(G_3\) 拼起来的图中跑 bfs 即可,即 bfs 过程中将两个图的 bitset 或起来即可。
最后复杂度为 \(O(\frac{nq}{B} + q \frac{B^2}{\omega} + \frac{n^2}{\omega})\),取 \(B=300\) 即可通过。
注意每个块内要清空的数组的清空的范围。
#include<bits/stdc++.h>
#define double long double
using namespace std;
const int N=5e4+10,M=1e5+10,len=300,K=len+10;
bitset<4*K>s1[N],s2[4*K],s3[4*K];
int op[M],U[M],V[M],A[M],B[M],n,m,q,c[M],vis[M],cnt,vis1[N],ss[N],Ans,du[N];
int dfn[N],low[N];stack<int>s;
vector<int>g1[N],g2[N];
int anss[M],mp[4*K][4*K],mp1[N];
inline int read(){
int ans=0,f=1;
char c=getchar();
while(c<48||c>57) (c==45?f=-1:1),c=getchar();
while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
return ans*f;
}
void tarjan(int u){
dfn[u]=low[u]=++cnt;s.push(u),vis1[u]=1;
for (auto v:g1[u])
if (!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if (vis1[v]) low[u]=min(low[u],dfn[v]);
if (dfn[u]==low[u]){
Ans++;
while(s.top()^u){
int x=s.top();s.pop();
ss[x]=Ans,vis1[x]=0;
}
int x=s.top();s.pop();
ss[x]=Ans,vis1[x]=0;
}
}
inline bool bfs(int x,int y){
bitset<4*K>tmp;tmp.set();
queue<int>q;q.push(x);
while(!q.empty()){
int u=q.front();q.pop();
bitset<4*K>xx=(tmp&(s2[u]|s3[u]));
for (int v=xx._Find_first();v<4*K;v=xx._Find_next(v)){
if (v==y) return 1;
q.push(v),tmp.reset(v);
}
}
return 0;
}
main(){
n=read(),m=read(),q=read();
for (int i=1;i<=m;i++){
int u=read(),v=read();
U[i]=u,V[i]=v;
c[i]=1;
}
for (int i=1;i<=q;i++){
op[i]=read();
if (op[i]==1) A[i]=read();
if (op[i]==2) A[i]=read(),B[i]=read();
}
for (int l=1;l<=q;l+=len){
vector<int>tmp;
int r=min(q,l+len-1);
for (int i=1;i<=n;i++) dfn[i]=low[i]=vis1[i]=ss[i]=du[i]=0;
for (int i=1;i<=n;i++) s1[i].reset(),g1[i].clear(),g2[i].clear();
for (int i=1;i<=m;i++) vis[i]=0;
for (int i=l;i<=r;i++) if (op[i]==1) vis[A[i]]=1,tmp.push_back(U[A[i]]),tmp.push_back(V[A[i]]); else tmp.push_back(A[i]),tmp.push_back(B[i]);
for (int i=1;i<=m;i++) if (!vis[i]&&c[i]==1) g1[U[i]].push_back(V[i]);
sort(tmp.begin(),tmp.end());tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());
for (int i=0;i<tmp.size();i++) mp1[tmp[i]]=i;
cnt=Ans=0;
for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;i++)
for (auto j:g1[i]) if (ss[i]^ss[j]) g2[ss[i]].push_back(ss[j]),du[ss[j]]++;
for (int i=0;i<tmp.size();i++) s1[ss[tmp[i]]].set(i);
queue<int>q;vector<int>topsort;
for (int i=1;i<=Ans;i++) if (!du[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();topsort.push_back(u);
for (auto v:g2[u]) if (--du[v]==0) q.push(v);
}
reverse(topsort.begin(),topsort.end());
for (auto i:topsort) for (auto j:g2[i]) s1[i]|=s1[j];
for (int i=0;i<tmp.size();i++)
for (int j=0;j<tmp.size();j++) if (s1[ss[tmp[i]]][j]) s2[i].set(j);
for (int i=1;i<=m;i++) if (vis[i]&&c[i]) mp[mp1[U[i]]][mp1[V[i]]]++,s3[mp1[U[i]]].set(mp1[V[i]]);
for (int i=l;i<=r;i++)
if (op[i]==2) anss[i]=bfs(mp1[A[i]],mp1[B[i]]);
else{
int u=U[A[i]],v=V[A[i]];
if (c[A[i]]){
mp[mp1[u]][mp1[v]]--;
if (mp[mp1[u]][mp1[v]]==0) s3[mp1[u]].reset(mp1[v]);
}
else{
mp[mp1[u]][mp1[v]]++;
if (mp[mp1[u]][mp1[v]]) s3[mp1[u]].set(mp1[v]);
}
c[A[i]]^=1;
}
for (int i=0;i<tmp.size();i++) for (int j=0;j<tmp.size();j++) mp[i][j]=0;
for (int i=0;i<tmp.size();i++) s2[i].reset(),s3[i].reset();
}
for (int i=1;i<=q;i++) if (op[i]==2) puts(anss[i]?"YES":"NO");
return 0;
}

浙公网安备 33010602011771号