版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88735973
分析:
分块+st表+bitset卡常
把公路分成k块,内部通过bitset处理出连通状况。
每次询问,把连续的一些块通过st表得到边,再用两次dfs求强连通分量的方法,合并这些边,得到新的连通状况。
#include<cstdio>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<bitset>
#include<vector>
#define SF scanf
#define PF printf
#define MAXM 300010
#define MAXN 160
#define MAXB 800
using namespace std;
const int k=400;
pair<int,int> l[MAXM];
bitset<MAXN> f1[MAXB][12][MAXN],f0[MAXB][12][MAXN],tmp0[MAXN];
bitset<MAXN> f3[MAXB][12][MAXN],f2[MAXB][12][MAXN],tmp1[MAXN];
bitset<MAXN> vis;
int stk[MAXN],top;
void dfs1(int x){
vis[x]=0;
bitset<MAXN> now=vis&tmp0[x];
while(now.any()){
int pos=now._Find_next(0);
dfs1(pos);
now=vis&tmp0[x];
}
stk[++top]=x;
}
int dfs2(int x){
vis[x]=0;
bitset<MAXN> now=vis&tmp1[x];
int res=1;
while(now.any()){
int pos=now._Find_next(0);
res+=dfs2(pos);
now=vis&tmp1[x];
}
return res;
}
int n,m,q;
int query(){
top=0;
for(int i=1;i<=n;i++)
vis[i]=1;
for(int i=1;i<=n;i++)
if(vis[i]==1)
dfs1(i);
for(int i=1;i<=n;i++)
vis[i]=1;
int res=0;
for(int i=n;i>=1;i--)
if(vis[stk[i]]==1){
int siz=dfs2(stk[i]);
res+=siz*(siz-1)/2;
}
return res;
}
void ins(int L,int R,int id){
int l1=(id-1)*k;
int r1=id*k-1;
L=max(l1,L);
R=min(r1,R);
for(int i=L;i<=R;i++){
tmp0[l[i].first][l[i].second]=1;
tmp1[l[i].second][l[i].first]=1;
}
}
int blo[MAXM],maxf[MAXB];
int main(){
freopen("friend.in","r",stdin);
freopen("friend.out","w",stdout);
SF("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++){
SF("%d%d",&l[i].first,&l[i].second);
blo[i]=i/k+1;
}
int tot=m/k+1;
for(int i=1;i<=m;i++){
f0[blo[i]][0][l[i].first][l[i].second]=1;
f1[blo[i]][0][l[i].first][l[i].second]=1;
f2[blo[i]][0][l[i].second][l[i].first]=1;
f3[blo[i]][0][l[i].second][l[i].first]=1;
}
for(int i=1;i<=tot;i++)
for(int j=1;(1<<j)<=i;j++)
maxf[i]=j;
for(int i=1;i<11;i++)
for(int j=1;j<=tot;j++)
for(int l=1;l<=n;l++){
f0[j][i][l]=f0[j][i-1][l]|f0[min(tot,j+(1<<(i-1)))][i-1][l];
f2[j][i][l]=f2[j][i-1][l]|f2[min(tot,j+(1<<(i-1)))][i-1][l];
}
for(int i=1;i<11;i++)
for(int j=tot;j>=1;j--)
for(int l=1;l<=n;l++){
f1[j][i][l]=f1[j][i-1][l]|f1[max(1,j-(1<<(i-1)))][i-1][l];
f3[j][i][l]=f3[j][i-1][l]|f3[max(1,j-(1<<(i-1)))][i-1][l];
}
int L,R;
for(int i=1;i<=q;i++){
SF("%d%d",&L,&R);
int L1=blo[L];
int R1=blo[R];
for(int j=1;j<=n;j++) tmp0[j].reset(),tmp1[j].reset();
ins(L,R,L1);
ins(L,R,R1);
L1++;
R1--;
if(L1<=R1){
int dis=R1-L1+1;
for(int j=1;j<=n;j++){
tmp0[j]|=f0[L1][maxf[dis]][j]|f1[R1][maxf[dis]][j];
tmp1[j]|=f2[L1][maxf[dis]][j]|f3[R1][maxf[dis]][j];
}
}
PF("%lld\n",query());
}
}