题解:http://www.cnblogs.com/y7070/p/5412793.html
暴力分块
”对于每一组,将符合一组a的询问选出来,将这些询问和这一块之前的边(a一定小于这些询问)按b排序,然后交替插入,询问,对于一个询问,在当前块也有可能有满足的边,我们将其加入,考虑后并撤销“
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; struct event{ int u,v,a,b; int idx; }A[N],Q[N],tmp[N]; int cnt; bool cmpa(const event A,const event B){ return A.a<B.a; } bool cmpb(const event A,const event B){ return A.b<B.b; } int n,m,tot; int ans[N]; struct Op{ int x,y,xmaxa,xmaxb,ymaxa,ymaxb,ysize; Op(int x=0,int y=0,int xmaxa=0,int xmaxb=0,int ymaxa=0,int ymaxb=0,int ysize=0):x(x),y(y),xmaxa(xmaxa),xmaxb(xmaxb),ymaxa(ymaxa),ymaxb(ymaxb),ysize(ysize) {} }op[N]; int pnt; int fat[N],maxa[N],maxb[N],size[N]; inline int Fat(int u){ return u==fat[u]?u:Fat(fat[u]); } inline void Merge(int u,int v,int a,int b){ u=Fat(u); v=Fat(v); if (size[u]>size[v]) swap(u,v); op[++pnt]=(Op){u,v,maxa[u],maxb[u],maxa[v],maxb[v],size[v]}; if (u==v) { maxa[u]=max(maxa[u],a); maxb[u]=max(maxb[u],b); return; } size[v]+=size[u]; maxa[v]=max(maxa[v],max(a,maxa[u])); maxb[v]=max(maxb[v],max(b,maxb[u])); fat[u]=v; } inline void Restore(){ for (int i=pnt;i;i--) { maxa[op[i].x]=op[i].xmaxa; maxb[op[i].x]=op[i].xmaxb; maxa[op[i].y]=op[i].ymaxa; maxb[op[i].y]=op[i].ymaxb; size[op[i].y]=op[i].ysize; fat[op[i].x]=op[i].x; } } int main() { int st,ed,SIZE; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); SIZE=sqrt(n); for (int i=1;i<=m;i++) read(A[i].u),read(A[i].v),read(A[i].a),read(A[i].b); read(tot); for (int i=1;i<=tot;i++) read(Q[i].u),read(Q[i].v),read(Q[i].a),read(Q[i].b),Q[i].idx=i; sort(A+1,A+m+1,cmpa); sort(Q+1,Q+tot+1,cmpb); for (st=1;st<=m;st=ed+1) { ed=min(st+SIZE-1,m); cnt=0; for (int i=1;i<=tot;i++) if (Q[i].a>=A[st].a && (ed==m || Q[i].a<A[ed+1].a)) tmp[++cnt]=Q[i]; if (!cnt) continue; sort(A+1,A+st,cmpb); for (int i=1;i<=n;i++) fat[i]=i,size[i]=1,maxa[i]=maxb[i]=-1; for (int i=1,j=1;i<=cnt;i++) { while (j<st && A[j].b<=tmp[i].b) Merge(A[j].u,A[j].v,A[j].a,A[j].b),j++; pnt=0; for (int k=st;k<=ed;k++) if (A[k].a<=tmp[i].a && A[k].b<=tmp[i].b) Merge(A[k].u,A[k].v,A[k].a,A[k].b); int fx=Fat(tmp[i].u),fy=Fat(tmp[i].v); if (fx==fy && maxa[fx]==tmp[i].a && maxb[fx]==tmp[i].b) ans[tmp[i].idx]=1; Restore(); } } for (int i=1;i<=tot;i++) ans[i]?printf("Yes\n"):printf("No\n"); return 0; }