线段树分治学习笔记

比赛又双叒叕遇到新科技了(

线段树分治,是一种基于时间的分治思想(类比 CDQ 分治)。

利用线段树将某个区间至多分成 \(\log\) 段的思想,可以方便得处理一些便于插入和撤销的操作。

例如板子题

判断二分图可以利用扩展域并查集,而且利用可撤销并查集(仅按秩合并 + 栈记录)可以做到单次 \(O(\log n)\)

但是关键是边的消失和出现不太好处理,可以利用线段树的结构,将操作挂在代表区间的节点上,统一处理。

这样就完美 \(O(n\log n\log k)\) 解决了,其中 \(k\) 是时间维。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

typedef pair<int, int> PII;
#define MP make_pair
#define U  first
#define V  second

const int N = 1e5 + 10;
int n, m, k, tot, fa[N << 1], h[N << 1];
PII stk[N];
vector<PII> G[N << 2];

int read(){
	int x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') f = (c == '-') ? -1 : 1, c = getchar();
	while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
	return x * f;
}

void Modify(int p, int l, int r, int L, int R, int u, int v){
	if(L <= l && r <= R) {G[p].push_back(MP(u, v)); return;}
	int mid = (l + r) >> 1;
	if(L <= mid) Modify(p << 1, l, mid, L, R, u, v);
	if(R >  mid) Modify(p << 1 | 1, mid + 1, r, L, R, u, v);
}

int Get(int x){
	if(x == fa[x]) return x;
	return Get(fa[x]);
}

void Merge(int u, int v){
	int fu = Get(u), fv = Get(v);
	if(fu == fv) return;
	if(h[fu] > h[fv]) swap(fu, fv);
	stk[++ tot] = MP(fu, h[fu] == h[fv]);
	fa[fu] = fv, h[fv] += (h[fu] == h[fv]);
}

void Work(int p, int l, int r){
	bool flag = true;
	int las = tot;
	for(int i = 0; i < (int) G[p].size(); i ++){
		int u = G[p][i].U;
		int v = G[p][i].V;
		if(Get(u) == Get(v)) {flag = false; break;}
		Merge(u, v + n);
		Merge(u + n, v);
	}
	if(flag){
		if(l == r) puts("Yes");
		else{
			int mid = (l + r) >> 1;
			Work(p << 1, l, mid);
			Work(p << 1 | 1, mid + 1, r);
		}
	}
	else
		for(int i = l; i <= r; i ++) puts("No");
	while(tot != las){
		int u = stk[tot].U, v = stk[tot].V;
		h[fa[u]] -= v; fa[u] = u; tot --;
	}
}

int main(){
	n = read(), m = read(), k = read();
	for(int i = 1; i <= m; i ++){
		int u = read()    , v = read();
		int l = read() + 1, r = read();
		Modify(1, 1, k, l, r, u, v);
	}
	for(int i = 1; i <= (n << 1); i ++) fa[i] = i, h[i] = 1;
	Work(1, 1, k);
	return 0;
}
posted @ 2021-08-14 21:57  LPF'sBlog  阅读(44)  评论(0编辑  收藏  举报