题解: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;
}