线段树分治求调,悬二关
查看原帖
线段树分治求调,悬二关
174477
sdyzpf楼主2024/3/14 17:19
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k,ans[100005],fa[200005],siz[200005];
stack<int> stk;
struct node{
	int l,r;
	vector<pair<int,int> >v;
}t[400005];
int getf(int x){
	if(x==fa[x]) return x;
	return getf(fa[x]);
}
void merge(int x,int y){
	int nx=getf(x),ny=getf(y);
	if(siz[nx]>siz[ny]) swap(nx,ny);
	fa[nx]=ny,siz[ny]+=siz[nx];
	stk.push(nx);
}
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r;
	if(l==r) return;
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
void insert(int p,int l,int r,int x,int y){
	if(l<=t[p].l&&t[p].r<=r){
		t[p].v.push_back({x,y});
		return;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(l<=mid) insert(p*2,l,mid,x,y);
	if(r>mid)  insert(p*2+1,mid+1,r,x,y);
}
void solve(int p){
	int o=stk.size();
	for(int i=0;i<t[p].v.size();i++){
		int nx=getf(t[p].v[i].first);
		int ny=getf(t[p].v[i].second);
		if(nx==ny) goto clear;
		merge(t[p].v[i].first+n,t[p].v[i].second);
		merge(t[p].v[i].first,t[p].v[i].second+n);
	}
	if(t[p].l==t[p].r) ans[t[p].l]=1;
	else solve(p*2),solve(p*2+1);
	clear:while(stk.size()>o--){
		siz[fa[stk.top()]]-=siz[stk.top()];
		fa[stk.top()]=stk.top();
		stk.pop();
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m>>k;
	build(1,1,k);
	for(int i=1;i<=2*n;i++) fa[i]=i,siz[i]=1;
	for(int i=1;i<=m;i++){
		int x,y,l,r;
		cin>>x>>y>>l>>r;
		insert(1,l+1,r,x,y);
	}
	solve(1);
	for(int i=1;i<=k;i++)
		if(ans[i]) cout<<"Yes\n";
		else cout<<"No\n";
	return 0;
}
2024/3/14 17:19
加载中...