蓝题训练9.26P5787 【模板】线段树分治 / 二分图

P5787 【模板】线段树分治 / 二分图

Tag:略
题意:略

题解:线段树分治板子

参考代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll N = 1e5 + 7, M = 2e5 + 7;
ll n, m, k, u[M], v[M], fa[N<<1], sz[N<<1];
struct T {
	ll l, r;
	vector<ll> e;
} t[N<<2];
stack<pair<ll,ll>> s;
ll ls(ll x){
	return x<<1;
}
ll rs(ll x){
	return (x<<1)|1;
}
void build(ll p, ll l, ll r) {
	t[p].l = l, t[p].r = r;
	if (l == r) return;
	ll mid=(l+r)/2;
	build(ls(p), l, mid), 
	build(rs(p), mid + 1, r);
}
void ins(ll p, ll l, ll r, ll x) {
	if (t[p].l >= l && t[p].r <= r) {
		t[p].e.push_back(x);
		return;
	}
	ll mid = (t[p].l + t[p].r) / 2;
	if (l <= mid) ins(ls(p), l, r, x);
	if (r > mid) ins(rs(p), l, r, x);
}
inline ll find(ll x) {
	while (x != fa[x]) x = fa[x];
    return x;
}
inline void merge(ll x, ll y) {
	if (x == y) return;
	if (sz[x] > sz[y]) swap(x, y);
	s.push({x,sz[x]}), fa[x] = y, sz[y]+=sz[x];
}
void dfs(ll p, ll l, ll r) {
	bool ok = 1;
	ll o = s.size();
	for (ll i = 0; i < t[p].e.size(); i++) {
		ll x = t[p].e[i], z = find(u[x]), y = find(v[x]);
		if (z == y) {
			for (ll j = l; j <= r; j++) cout<<"No\n";
			ok = 0;
			break;
		}
		ll zz=find(u[x]+n),yy=find(v[x]+n);
		merge(zz, y), merge(yy, z);
	}
	if (ok) {
		ll mid=(l+r)/2;
		if (l == r) cout<<"Yes\n";
		else dfs(ls(p), l, mid), dfs(rs(p), mid + 1, r);
	}
	while (s.size() > o) {
		sz[fa[s.top().first]] -= s.top().second;
		fa[s.top().first] = s.top().first;
		s.pop();
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m>>k;
	build(1,1,k);
	for (int i = 1, l, r; i <= m; i++) {
		cin>>u[i]>>v[i]>>l>>r;
		if (l<r) ins(1,l + 1,r,i);
	}
	for (int i = 1; i <= 2*n; i++) fa[i] = i,sz[i]=1;//初始化
	dfs(1, 1, k);
	return 0;
}



posted @ 2026-10-29 19:50  pigeon666  阅读(4)  评论(0)    收藏  举报