[bzoj4025] 二分图
暴力的话可以拿并查集解决,然后线段树分治
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
#define xx first
#define yy second
typedef pair<int,int> pii;
stack<pii> stk[N];
int cnt[N];
int n,m,T;
inline void insert(int x,int l,int r,int ql,int qr,pii opt){
int mid=(l+r)>>1;
if(ql<=l&&qr>=r){
stk[x].push(opt);++cnt[x];
return;
}
if(ql<=mid)insert(x<<1,l,mid,ql,qr,opt);
if(qr>mid)insert(x<<1|1,mid+1,r,ql,qr,opt);
}
stack<pii> opt;
int fa[N],sz[N],val[N];
int find(int x){
return fa[x]==x?fa[x]:find(fa[x]);
}
int dep(int x){
return fa[x]==x?val[x]:dep(fa[x])+val[x];
}
inline void run(int x,int l,int r,bool ans){
while(!stk[x].empty()){
pii op=stk[x].top();stk[x].pop();
int X=find(op.xx),Y=find(op.yy);
if(X!=Y){
if(sz[X]>sz[Y])swap(X,Y);
opt.push(pii(X,Y));
val[X]=dep(op.xx)+dep(op.yy)+1;
sz[Y]+=sz[X],fa[X]=Y;
}else{
if(dep(op.xx)%2==dep(op.yy)%2)ans=false;
opt.push(pii(0,0));
}
}
int mid=(l+r)>>1;
if(l==r){
if(ans==true)printf("Yes\n");
else printf("No\n");
}else{
run(x<<1,l,mid,ans);run(x<<1|1,mid+1,r,ans);
}
for(int i=1;i<=cnt[x];i++){
pii op=opt.top();opt.pop();
if(op.xx==0)continue;
fa[op.xx]=op.xx;val[op.xx]=0;
sz[op.yy]-=sz[op.xx];
}
}
int main()
{
scanf("%d%d%d",&n,&m,&T);
for(int i=1;i<=m;i++){
int u,v,l,r;scanf("%d%d%d%d",&u,&v,&l,&r);++l;
if(l<=r)insert(1,1,T,l,r,pii(u,v));
}
for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1;
run(1,1,T,true);
}