(O(nq))把大于((a,b))的边加入,(u,v)在的连通块最小为((a,b))即可
查两维又难删除,回滚莫队?
又不要脸地去看标程了,貌似分了块,难不成是真的?
等等等,又看错题了,是最小公倍数不是最大公约数
仔细想想分块这个又是干啥的?可以把边按a排序,然后分块,a在一块内的一起处理询问,把后几块的重新b排序,依次加入,每个询问再单独加当前块的(和回滚莫队差不多,只不过多排一遍序)
时间复杂度(O(mlogmsqrt{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);
}