HNOI2016最小公倍数


\(O(nq)\)把大于\((a,b)\)的边加入,\(u,v\)在的连通块最小为\((a,b)\)即可

查两维又难删除,回滚莫队?

又不要脸地去看标程了,貌似分了块,难不成是真的?

等等等,又看错题了,是最小公倍数不是最大公约数

仔细想想分块这个又是干啥的?可以把边按a排序,然后分块,a在一块内的一起处理询问,把后几块的重新b排序,依次加入,每个询问再单独加当前块的(和回滚莫队差不多,只不过多排一遍序)

时间复杂度\(O(mlogm\sqrt{mlogm})\)

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=1e5+4;
int n,m,Q,B,BB;
int bb[N<<1],bl[N],br[N],ans[N]; 
struct edge{int u,v,a,b;}e[N<<1],qe[N<<1];
struct ques{int u,v,a,b,id,bk;}q[N];
inline bool compa(const edge &x,const edge &y){
	return x.a<y.a;
}
inline bool compb(const edge &x,const edge &y){
	return x.b<y.b;
}
inline bool compq(const ques &x,const ques &y){
	return x.bk==y.bk?x.b<y.b:x.bk<y.bk;
}
int top,fa[N],siz[N],mxa[N],mxb[N];
int find(int x){
	return fa[x]==x?x:find(fa[x]);
}
struct modi{int v,u,ma,mb,sz;}st[N];
inline void add(edge x){
	int fu=find(x.u),fv=find(x.v);
	if(siz[fu]<siz[fv])fu^=fv^=fu^=fv;
	st[++top]=(modi){fv,fu,mxa[fu],mxb[fu],siz[fu]};
	mxa[fu]=max(mxa[fu],x.a);
	mxb[fu]=max(mxb[fu],x.b);
	if(fu==fv){
		st[top].v=0;
		return;
	}
	fa[fv]=fu;
	siz[fu]+=siz[fv];
	mxa[fu]=max(mxa[fu],mxa[fv]);
	mxb[fu]=max(mxb[fu],mxb[fv]);
}
inline void delet(){
	if(st[top].v)fa[st[top].v]=st[top].v;
	int u=st[top].u;
	mxa[u]=st[top].ma;
	mxb[u]=st[top].mb;
	siz[u]=st[top].sz;
	top--;
}
int main(){
	n=read();m=read();
	for(int i=1,u,v,a,b;i<=m;i++){
		u=read();v=read();a=read();b=read();
		e[i]=(edge){u,v,a,b};
	}
	sort(e+1,e+m+1,compa);
	B=sqrt(m*log(m));BB=1;
	for(int i=1;i<=m;i+=B,BB++){
		bl[BB]=i;br[BB]=min(m,i+B-1);
		bb[BB]=e[br[BB]].a;
	} 
	bb[BB]=1000000007;bl[BB]=m+1;
	Q=read();
	for(int i=1,u,v,a,b,k;i<=Q;i++){
		u=read();v=read();a=read();b=read();
		k=upper_bound(bb+1,bb+BB+1,a)-bb;
		q[i]=(ques){u,v,a,b,i,k};
	}
	sort(q+1,q+Q+1,compq);
	for(int i=1,l,fu,fv;i<=Q;i++){
		if(q[i].bk!=q[i-1].bk){
			memcpy(qe,e,sizeof(e));
			sort(qe+1,qe+bl[q[i].bk],compb);
			l=1;top=0;
			for(int j=1;j<=n;j++){
				fa[j]=j;
				mxa[j]=mxb[j]=-1;//
				siz[j]=1;
			}
		}
		while(l<bl[q[i].bk]&&qe[l].b<=q[i].b){
			add(qe[l++]);
		}
		for(int j=bl[q[i].bk];j<=br[q[i].bk]&&qe[j].a<=q[i].a;j++){
			if(qe[j].b<=q[i].b)add(qe[j]);
		}
		fu=find(q[i].u);fv=find(q[i].v);
		if(fu==fv&&mxa[fu]==q[i].a&&mxb[fu]==q[i].b)ans[q[i].id]=1;
		for(int j=bl[q[i].bk];j<=br[q[i].bk]&&qe[j].a<=q[i].a;j++){
			if(qe[j].b<=q[i].b)delet();
		}
	}
	for(int i=1;i<=Q;i++)
		if(ans[i])puts("Yes");
		else puts("No");
	return (0-0);
}

猜你喜欢

转载自www.cnblogs.com/aurora2004/p/12628674.html