CF576E Painting Edges [线段树分治,可撤销并查集]

Posted isaunoya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF576E Painting Edges [线段树分治,可撤销并查集]相关的知识,希望对你有一定的参考价值。

板子题.jpg
不同颜色互不影响,所以判断每种颜色有没有奇环就可以了,顺便判一下联不联通.jpg

#include <bits/stdc++.h>
#define rep(i , x , y) for(register int i = (x) , _## i = (y + 1) ; i < _## i ; i ++)
#define Rep(i , x , y) for(register int i = (x) , _## i = (y - 1) ; i > _## i ; i --)
using namespace std ;
//#define int long long
using ll = long long ;
using pii = pair < int , int > ;
const static int _ = 1 << 20 ;
char fin[_] , * p1 = fin , * p2 = fin ;
inline char gc() {
	return (p1 == p2) && (p2 = (p1 = fin) + fread(fin , 1 , _ , stdin) , p1 == p2) ? EOF : * p1 ++ ;
}
inline int read() {
	bool sign = 1 ;
	char c = 0 ;
	while(c < 48) ((c = gc()) == 45) && (sign = 0) ;
	int x = (c & 15) ;
	while((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15) ;
	return sign ? x : -x ;
}
template < class T > void print(T x , char c = ‘
‘) {
	(x == 0) && (putchar(48)) , (x < 0) && (putchar(45) , x = -x) ;
	static char _st[100] ;
	int _stp = 0 ;
	while(x) _st[++ _stp] = x % 10 ^ 48 , x /= 10 ;
	while(_stp) putchar(_st[_stp --]) ;
	putchar(c) ;
}
template < class T > void cmax(T & x , T y) {
	(x < y) && (x = y) ;
}
template < class T > void cmin(T & x , T y) {
	(x > y) && (x = y) ;
}

int N , M , K , Q ;
const int SZ = 5e5 + 10 ;
int id[SZ] , las[SZ] , L[SZ] , R[SZ] ;
int pre[SZ] , col[SZ] ;
struct Node {
	int u , v , col ;
	bool s ;
} edge[SZ << 1] ;
struct Union {
	int fa[SZ] , f[SZ] , d[SZ] ;
	int find(int x) {
		return x == fa[x] ? x : find(fa[x]) ;
	}
	int dis(int x) {
		int y = 0 ;
		while(x ^ fa[x]) {
			y ^= f[x] ;
			x = fa[x] ;
		}
		return y ;
	}
	void cancel(Node a) {
		f[fa[a.u] = a.u] = 0 ;
		d[a.v] -= a.s ;
	}
	bool connected(int x , int y) {
		return find(x) == find(y) ;
	}
	Node Merge(int x , int y , int col) {
		int fx = find(x) , fy = find(y) ;
		if(d[fx] > d[fy]) swap(fx , fy) , swap(x , y) ;
		int w = dis(x) ^ dis(y) ^ 1 ;
		Node res = { fx , fy , col , 0 } ;
		f[fx] = w ; fa[fx] = fy ;
		if(d[fx] == d[fy]) {
			++ d[fy] ;
			res.s |= 1 ;
		}
		return res ;
	}
} G[55] ;
void cancel(stack < Node > s) {
	while(s.size()) {
		G[s.top().col].cancel(s.top()) ;
		s.pop() ;
	}
}
vector < int > vec[SZ << 2] ;
void upd(int a , int b , int l , int r , int rt , int id) {
//	print(l , ‘ ‘) ; print(r , ‘
‘) ;
	if(a <= l && r <= b) {
		vec[rt].push_back(id) ;
		return ;
	}
	int mid = l + r >> 1 ;
	if(a <= mid) upd(a , b , l , mid , rt << 1 , id) ;
	if(b > mid) upd(a , b , mid + 1 , r , rt << 1 | 1 , id) ;
}
void solve(int l , int r , int k) {
	stack < Node > s ;
	for(auto Id : vec[k]) {
		Node e = edge[Id] ;
		if(! e.col) continue ;
		int u = e.u , v = e.v , col = e.col ;
		if(G[col].connected(u , v)) continue ;
		s.push(G[col].Merge(u , v , col)) ;
	}
	if(l == r) {
		Node e = edge[id[l]] ;
		int w = G[col[l]].dis(e.u) ^ G[col[l]].dis(e.v) ^ 1 ;
		bool t = G[col[l]].connected(e.u , e.v) ;
		cancel(s) ;
		if(! t || ! w) {
			puts("YES") ;
			edge[id[l]].col = col[l] ;
			return ;
		}
		else {
			puts("NO") ;
			return ;
		}
	}
	int mid = l + r >> 1 ;
	solve(l , mid , k << 1) ;
	solve(mid + 1 , r , k << 1 | 1) ;
	cancel(s) ;
}

signed main() {
#ifdef _WIN64
	freopen("testdata.in" , "r" , stdin) ;
#endif
	N = read() ; M = read() ; K = read() ; Q = read() ;
	rep(i , 1 , K) 
		rep(j , 1 , N) G[i].fa[j] = j ;
	rep(i , 1 , M) {
		int x = read() , y = read() ;
		edge[i] = { x , y , 0 } ;
	}
	rep(i , 1 , Q) {
		int x = read() , y = read() ;
		id[i] = x ; col[i] = y ;
		if(las[x]) R[las[x]] = i - 1 ;
		pre[i] = las[x] ;
		las[x] = i ;
		L[i] = i + 1 ;
		R[i] = Q ;
	}
	rep(i , 1 , Q)
		if(L[i] <= R[i]) upd(L[i] , R[i] , 1 , Q , 1 , id[i]) ;
	solve(1 , Q , 1) ;
//	puts("OK") ;
	return 0 ;
}

以上是关于CF576E Painting Edges [线段树分治,可撤销并查集]的主要内容,如果未能解决你的问题,请参考以下文章

CF576E Painting Edges

576E - Painting Edges

CF1198E Rectangle Painting 2

CF1479B Painting the Array

cf 448 C. Painting Fence

题解 CF1242A Tile Painting