题解:
好暴力的一道题啊。。
容易发现如果把所有边看做二维平面上的点,那么我们要查询某个左下方的矩形的连通性以及最大值。
这个用数据结构不好维护,用稍微暴力一点的分块来维护。
按照横坐标 a a 分为块,询问放到对应块并按照 b b 的顺序来对于前面的块做扫描线,每个块会被扫描次。
还要考虑本块的贡献,这个可以直接暴力扫一遍,因为只有 m‾‾√ m 条,然后用个支持撤销的按秩合并的并查集维护一下就行了,时间复杂度 O(mm‾‾√logn) O ( m m log n ) 。
#include <bits/stdc++.h>
using namespace std;
inline int rd() {
char ch=getchar(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
return i*f;
}
const int N=5e4+50,M=1e5+50,B=1e3+50;
int n,m,q,bl,h,ans[N],tot,bg[B],ed[B],pos[B];
struct data {
int u,v,a,b;
data() {}
data(int u,int v,int a,int b):u(u),v(v),a(a),b(b){}
friend inline bool operator <(const data &a,const data &b) {
if(a.a!=b.a) return a.a<b.a;
return a.b<b.b;
}
} op[M];
inline bool cmp(const data &a,const data &b) {
if(a.b!=b.b) return a.b<b.b;
return a.a<b.a;
}
struct ask{
int id,u,v,a,b;
friend inline bool operator <(const ask &a,const ask &b) {
if(a.b!=b.b) return a.b<b.b;
return a.a<b.a;
}
};
vector <ask> qry[B];
struct type{int f,a,b;};
int mxa[N],mxb[N],anc[N],rk[N];
inline type getanc(int i) {
if(i==anc[i]) return (type){i,mxa[i],mxb[i]};
return getanc(anc[i]);
}
struct type2 {int u,prea,preb,x,y;};
vector <type2> st;
inline type2 link(int x,int y,int a,int b) {
x=getanc(x).f, y=getanc(y).f;
type2 tp;
if(x==y) {
tp.u=0; tp.x=x;
} else {
if(rk[x]<rk[y]) swap(x,y);
tp.u=1+(rk[x]==rk[y]);
rk[x]+=(rk[x]==rk[y]);
tp.x=x; tp.y=y; anc[y]=x;
}
tp.prea=mxa[x]; tp.preb=mxb[x];
mxa[x]=max(mxa[x],max(a,mxa[y]));
mxb[x]=max(mxb[x],max(b,mxb[y]));
return tp;
}
inline void cut(type2 tp) {
if(tp.u) {
anc[tp.y]=tp.y; rk[tp.x]-=(tp.u-1);
}
mxa[tp.x]=tp.prea;
mxb[tp.x]=tp.preb;
}
int main() {
n=rd(), m=rd();
for(int i=1;i<=m;i++) op[i].u=rd(), op[i].v=rd(), op[i].a=rd(), op[i].b=rd();
sort(op+1,op+m+1);
bl=sqrt(m); h=(m-1)/bl+1;
for(int i=1;i<=h;i++)
bg[i]=(i-1)*bl+1, ed[i]=min(i*bl,m);
q=rd();
for(int i=1;i<=q;i++) {
int u=rd(), v=rd(), a=rd(), b=rd();
for(int j=h;j>=1;j--) {
if(op[ed[j]].a>=a && (op[ed[j-1]].a<=a || j==1)) {
qry[j].push_back((ask){i,u,v,a,b});
break;
}
}
}
for(int i=1;i<=h;i++) if(qry[i].size()) sort(qry[i].begin(),qry[i].end());
for(int i=1;i<=h;i++) sort(op+bg[i],op+ed[i]+1,cmp);
for(int i=1;i<=n;i++) anc[i]=i, mxa[i]=-1, mxb[i]=-1;
for(int i=1;i<=h;i++) {
for(int j=1;j<=n;j++) anc[j]=j, mxa[j]=-1, mxb[j]=-1;
for(int j=1;j<i;j++) pos[j]=bg[j];
for(int j=0;j<qry[i].size();++j) {
ask t=qry[i][j];
st.clear();
for(int p=1;p<i;p++)
for(;pos[p]<=ed[p] && op[pos[p]].b<=t.b;++pos[p])
link(op[pos[p]].u,op[pos[p]].v,op[pos[p]].a,op[pos[p]].b);
for(int p=bg[i];p<=ed[i] && op[p].b<=t.b; ++p)
if(op[p].a<=t.a) st.push_back(link(op[p].u,op[p].v,op[p].a,op[p].b));
type f1=getanc(t.u), f2=getanc(t.v);
if(f1.f==f2.f && f1.a==t.a && f1.b==t.b) ans[t.id]=1;
for(int p=st.size()-1;p>=0;p--) cut(st[p]);
}
}
for(int i=1;i<=q;i++) ans[i]?(puts("Yes")):(puts("No"));
}