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 [线段树分治,可撤销并查集]的主要内容,如果未能解决你的问题,请参考以下文章