杂题
有向图,问点 \(u\) 能否通过标号在 \(l\) 与 \(r\) 之间的边到达 \(v\) 。
\(n,q \leq 50000,m\leq 100000\)
#include<cstdio>
#include<cstring>
const int H=40000040;
char G[H],*_=G;
int read(){
int x=0;
while(*_<'0'||'9'<*_)_++;
while('0'<=*_&&*_<='9')x=x*10+(*_++^'0');
return x;
}
const int N=50050;
int tp;
#include<cmath>
#include<bitset>
std::bitset<N>f[N],Q[460],tmp;
#include<vector>
std::vector<int>ql[N<<1],qr[N<<1];
struct edge{
int u,v;
}e[N<<1];
struct query{
int u,v;
}h[N];
struct go{
go*net;int to,id;
}ea[N<<1],*tot=ea,*head[N];
int p[N<<1],d[N],qq[N];
void work(){
int i,l,r,n=read(),m=read(),q=read(),size=sqrt(m);
memset(d,0,sizeof(int)*(n+1));
for(i=0;i<n;i++)f[i].reset();Q[0].reset();
for(i=0;i<=m;i++)ql[i].clear(),qr[i].clear();
memset(head,0,sizeof(go*)*(n+1)),tot=ea;
for(i=0;i<m;i++)e[i].u=read(),e[i].v=read(),*++tot={head[e[i].u],e[i].v,i},head[e[i].u]=tot,d[e[i].v]++;
for(i=0;i<q;i++)h[i].u=read(),h[i].v=read(),l=read()-1,r=read()-1,ql[l].push_back(i),qr[r+1].push_back(i),f[h[i].v-1][i]=1;
for(i=0;i<m;i++){
for(int j:ql[i])Q[i/size][j]=1;
for(int j:qr[i])Q[i/size][j]=0;
if((i+1)%size==0)Q[(i+1)/size]=Q[i/size];
}
int *hh=qq,*tt=qq,cnt=0;
for(i=1;i<=n;i++)if(!d[i])*++tt=i;
while(++hh<=tt){
for(go*ii=head[*hh];ii;ii=ii->net){
d[ii->to]--,p[cnt++]=ii->id;
if(!d[ii->to])*++tt=ii->to;
}
}
for(i=m-1;i>=0;i--){
tmp.reset();
if(p[i]/size!=0)tmp=Q[(p[i]/size)-1];
for(int j=p[i]/size*size;j<=p[i];j++){
for(int k:ql[j])tmp[k]=1;
for(int k:qr[j])tmp[k]=0;
}
f[e[p[i]].u-1]|=(f[e[p[i]].v-1]&tmp);
}
for(i=0;i<q;i++){
if(f[h[i].u-1][i])puts("YES");
else puts("NO");
}
}
int main(){
fread(G,1,H,stdin);
int T=read();
while(T--)work();
return 0;
}