將邊按$a$從小到大排序,每$\sqrt{m}$個取一個關鍵點。
對於每個關鍵點,將這個點之前的邊以及要在這個關鍵點回答的詢問按$b$排序。
依次加入這個關鍵點之前的每條邊,用並查集維護每個連通塊$a$和$b$的最大值。
對於零碎部分,只有$\sqrt{m}$條邊,暴力加入即可。
用一個棧按時間記錄所有修改操作,然后撤銷操作即可。
時間復雜度$O(m\sqrt{m}\log n)$。
#include<cstdio> #include<algorithm> using namespace std; const int N=50010,M=100010; int n,m,Q,lim,i,j,k,o,x,y,ans[N],cnt,a[M],b[N]; int f[N],d[N],va[N],vb[N],co; struct P{int x,y,z;P(){}P(int _x,int _y,int _z){x=_x,y=_y;z=_z;}}op[N]; struct E{int x,y,a,b;}e[M],q[N]; inline bool cmpa(const E&a,const E&b){return a.a<b.a;} inline bool cmpe(int x,int y){return e[x].b<e[y].b;} inline bool cmpq(int x,int y){return q[x].b<q[y].b;} inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int F(int x){return f[x]==x?x:F(f[x]);} inline void merge(int x,int y,int a,int b,int type){ x=F(x),y=F(y); if(x!=y){ if(d[x]==d[y]){ if(type)op[++co]=P(1,x,d[x]); d[x]++; } if(d[x]<d[y])swap(x,y); if(type)op[++co]=P(0,y,y); f[y]=x; if(va[x]<va[y]&&va[y]>a){ if(type)op[++co]=P(2,x,va[x]); va[x]=va[y]; } if(vb[x]<vb[y]&&vb[y]>b){ if(type)op[++co]=P(3,x,vb[x]); vb[x]=vb[y]; } } if(va[x]<a){ if(type)op[++co]=P(2,x,va[x]); va[x]=a; } if(vb[x]<b){ if(type)op[++co]=P(3,x,vb[x]); vb[x]=b; } } inline void retrace(){ for(int i=co;i;i--){ if(!op[i].x)f[op[i].y]=op[i].z; else if(op[i].x==1)d[op[i].y]=op[i].z; else if(op[i].x==2)va[op[i].y]=op[i].z; else vb[op[i].y]=op[i].z; } co=0; } int main(){ read(n),read(m); while(lim*lim<m)lim++; for(i=1;i<=m;i++)read(e[i].x),read(e[i].y),read(e[i].a),read(e[i].b),a[i]=i; sort(e+1,e+m+1,cmpa); read(Q); for(i=1;i<=Q;i++)read(q[i].x),read(q[i].y),read(q[i].a),read(q[i].b); for(i=0;i<=m;i+=lim){ cnt=0; for(j=1;j<=Q;j++)if(q[j].a>=e[i].a&&(i+lim>m||q[j].a<e[i+lim].a))b[++cnt]=j; if(!cnt)continue; sort(a+1,a+i+1,cmpe); sort(b+1,b+cnt+1,cmpq); for(j=1;j<=n;j++)f[j]=j,d[j]=0,va[j]=vb[j]=-1; for(j=k=1;j<=cnt;j++){ while(k<=i&&e[a[k]].b<=q[b[j]].b){ merge(e[a[k]].x,e[a[k]].y,e[a[k]].a,e[a[k]].b,0); k++; } co=0; for(o=min(i+lim-1,m);o>i;o--) if(e[o].a<=q[b[j]].a&&e[o].b<=q[b[j]].b) merge(e[o].x,e[o].y,e[o].a,e[o].b,1); x=F(q[b[j]].x),y=F(q[b[j]].y); if(x==y&&va[x]==q[b[j]].a&&vb[x]==q[b[j]].b)ans[b[j]]=1; retrace(); } } for(i=1;i<=Q;i++)puts(ans[i]?"Yes":"No"); return 0; }