分析:
分块+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());}
}