【BZOJ】5218: [Lydsy2017省队十连测]友好城市 kosaraju+bitset+莫队

传送门:bzoj5218


题解

k o s a r a j u kosaraju kosaraju+莫队+压位+减枝
时间复杂度 O ( q ( n + n 2 32 ) ) O(q(\sqrt n + \dfrac{n^2}{32})) O(q(n +32n2))


代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define RI register
#define gc getchar()
#define si isdigit(ch)
#define ui unsigned int
#define buic(x) __builtin_ctz((x))
using namespace std;
const int N=155,M=3e5+10,MX=5e4+10;

int n,m,q,sum,num;
int block,in[M],ans[M];
int stk[N],top,df[N],dfn;
int bel[N],mp[N][N];

struct Q{int l,r,id;}qr[MX];
struct L{int u,v;}le[M];

struct BI{
	ui a[5];
	inline void itia(){memset(a,0,sizeof(a));}
	inline void st(int pos){a[pos>>5]|=(1<<(pos&31));}
	inline void flip(int pos){a[pos>>5]^=(1<<(pos&31));}
	inline bool exi(int pos){return (a[pos>>5]>>(pos&31))&1;}
}g[N],rvg[N],vis;

inline bool cmp(const Q&A,const Q&B){
   return in[A.l]==in[B.l]?A.r<B.r:A.l<B.l;
}

char ch;
inline void rd(int &x)
{
	ch=gc;x=0;
	for(;!si;ch=gc);
	for(;si;ch=gc) x=x*10+(ch^48);
}

inline void init()
{
	RI int i,j,k,t;
	rd(n);rd(m);rd(q);
	for(i=1;i<=m;++i){
		rd(le[i].u),rd(le[i].v);
		le[i].u--;le[i].v--;
	}
	for(i=1;i<=q;++i)
	 rd(qr[i].l),rd(qr[i].r),qr[i].id=i;
	block=sqrt(m)+1;
	for(i=1;i<=m;++i) in[i]=(i-1)/block+1;
	sort(qr+1,qr+q+1,cmp);
}

void dfs(int x)
{
	vis.st(x);ui res;
	for(RI int i=0;i<5;++i)
	 for(;;){
		res=g[x].a[i]-(g[x].a[i] & vis.a[i]);
		if(!res) break;
		dfs(i<<5|buic(res));
 	 }
 	df[++dfn]=x;
}

void dfss(int x)
{
	vis.st(x);ui res;int qw;num++;
	for(RI int i=0;i<5;++i)
	 for(;;){
	 	res=rvg[x].a[i]-(rvg[x].a[i]&vis.a[i]);
	 	if(!res) break;
	 	qw=i<<5|buic(res);
	 	bel[qw]=bel[x];
	 	dfss(qw);
	 }
}

inline void upp(int pos)
{
	sum=dfn=0;
	RI int i;
	vis.itia();
	for(i=n;i<160;++i) vis.st(i);
	for(i=0;i<n;++i) if(!vis.exi(i)) dfs(i);
	vis.itia();
	for(i=n;i<160;++i) vis.st(i);
	for(i=dfn;i;--i) if(!vis.exi(df[i])){
		num=0;bel[df[i]]=df[i];
		dfss(df[i]);sum+=(num-1)*num/2;
	}
	ans[pos]=sum;
}

void Mo()
{
	RI int um,i,j,cg,x,y;int l,r,L,R;
	l=qr[1].l;r=qr[1].r;
	for(i=l;i<=r;++i){
	   x=le[i].u;y=le[i].v;
	   mp[x][y]++;
	   if(mp[x][y]==1) 
	     g[x].st(y),rvg[y].st(x);
	}
    upp(qr[1].id);
    for(um=2;um<=q;++um){
    	cg=0;L=qr[um].l;R=qr[um].r;
    	if(L<l){
    		for(i=L;i<l;++i){
    			x=le[i].u;y=le[i].v;
    			mp[x][y]++;
    			if(mp[x][y]==1){
    				g[x].st(y);rvg[y].st(x);
    				if(!cg && bel[x]!=bel[y]) cg=1;
    			}
    		}
    		l=L;
    	}
    	if(R>r){
    		for(i=r+1;i<=R;++i){
    			x=le[i].u;y=le[i].v;
    			mp[x][y]++;
    			if(mp[x][y]==1){
    				g[x].st(y);rvg[y].st(x);
    				if(!cg && bel[x]!=bel[y]) cg=1;
    			}
    		}
    		r=R;
    	}
    	if(l<L){
    		for(i=l;i<L;++i){
    			x=le[i].u;y=le[i].v;
    			mp[x][y]--;
    			if(mp[x][y]==0){
    				g[x].flip(y);rvg[y].flip(x);
    				if((!cg) && bel[x]==bel[y]) cg=1;
    			}
    		}
    		l=L;
    	}
    	if(r>R){
    		for(i=R+1;i<=r;++i){
    			x=le[i].u;y=le[i].v;
    			mp[x][y]--;
    			if(mp[x][y]==0){
    				g[x].flip(y);rvg[y].flip(x);
    				if((!cg) && bel[x]==bel[y]) cg=1;
    			}
    		}
    		r=R;
    	}
    	if(cg) upp(qr[um].id);
    	else ans[qr[um].id]=sum;
    }
    for(i=1;i<=q;++i) printf("%d\n",ans[i]);
}

int main(){
	init();
    Mo();
    return 0;
}

你可能感兴趣的:(kosaraju算法,莫队算法)