Mn Zn 求助线段树分治板板qwq。
const int MAXN=5e5+10,MAXM=1e6+10;
int N,M,K;
#define ls (p<<1)
#define rs (p<<1|1)
struct ST
{
int l,r;
std::vector<int>val;
}Tr[MAXN<<2];
struct Edges
{
int fr,to;
}Ed[MAXM];
bool ans[MAXN];
void build(int p,int l,int r)
{
Tr[p].l=l,Tr[p].r=r;
if(l==r) return ;
int mid=(l+r)>>1;
build(ls,l,mid),build(rs,mid+1,r);
}
void modifyX(int p,int l,int r,int v)
{
if(l>r) return ;
if(l<=Tr[p].l&&Tr[p].r<=r) return Tr[p].val.push_back(v),void();
int mid=(Tr[p].l+Tr[p].r)>>1;
if(l<=mid) modifyX(ls,l,r,v);
if(mid<r) modifyX(rs,l,r,v);
}
struct Dsu
{
int Rt[MAXN],Siz[MAXN],Stk[MAXN],Top;
inline void init(int n){ for(int i=1;i<=n;++i) Rt[i]=i,Siz[i]=1; }
inline int getRt(int x)
{
while(x!=Rt[x]) x=Rt[x];
return x;
}
inline void merge(int u,int v)
{
int p=getRt(u),q=getRt(v);
if(p==q) return ;
if(Siz[p]<Siz[q]) std::swap(p,q);
Siz[p]+=Siz[q],Rt[q]=p;
Stk[++Top]=q;
}
inline void back()
{
int q=Stk[Top--];
Siz[Rt[q]]-=Siz[q],Rt[q]=q;
}
inline void back(int x)
{
while(Top>x) back();
}
inline bool connect(int u,int v){ return (getRt(u)==getRt(v)); }
}Dsu;
void Divide_Conquer(int p,bool ok)
{
int Tim=Dsu.Top;
if(!Tr[p].val.empty()&&ok)
for(int v:Tr[p].val)
{
if(Dsu.connect(Ed[v].fr,Ed[v].to))
{
ok=0;
break;
}
else Dsu.merge(Ed[v].fr,Ed[v].to);
// printf("%d:%d %d %d %d %d\n",p,Ed[v].fr,Ed[v].to,Tr[p].l,Tr[p].r,ok);
}
if(Tr[p].l==Tr[p].r) return ans[Tr[p].l]=ok,void();
Divide_Conquer(ls,ok),Divide_Conquer(rs,ok);
Dsu.back(Tim);
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(N,M,K);
Dsu.init(N);
build(1,1,K);
for(int i=1,u,v,l,r;i<=M;++i)
{
read(u,v,l,r);Ed[i]=(Edges){u,v};
modifyX(1,l+1,r,i);
}
Divide_Conquer(1,1);
for(int i=1;i<=K;++i) puts(ans[i]?"Yes":"No");
return 0;
}
/*
*/