CF1290C·Prefix Enlightenment

Ann began to take a long time - did not seem to mutter Kazakhstan. Here is the portal - codeforces E # 616 Div2 the Prefix Enlightenment

Solution

This is a good question Kichiku ...... although quite simple but not so miss.

Problem solution Reference: bilibili a fairy up the main

The title has a very important condition: the intersection of any three sets is empty, which means that any one of the lights will only belong to a maximum of two sets . Again, i is assumed to have lights of two sets A and B can be controlled, then there are two cases:

1, i is closed, then A or B is not open to open, or not open A B open.
2, i was open, then either AB are open or not open.

It can be seen that there is a constraint relationship between the respective sets. Feels like graph theory, in fact disjoint-set on it. This question is an extension field with the right to disjoint-set . We each set are split into two domains [points], the operation represents an operation is not expressed, and then the operation comes with a weight of 1. We can even shrink the edge point based on the previously mentioned restrictive relationship, the right of each set value of the number needed is one such operation.

but! Obviously problematic. Because if the point i is limited only by one set, then the state of the two points of the set is fixed , there is a point that is representative of the state is not selected. We can put this point to even below 0, so all states and 0 are not connected to the election.

Embodied enumerated one by one, then light will be, and the state is added a corresponding relationship set in this lamp. Of course, our choice might be because the addition of new requirements and changes, so every time minus the first choice for the collection of contributions to the collection [that is associated with a series of operations to be subtracted, look at this code better understand some. ]

Look at the code.

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 600005
using namespace std;
typedef long long ll;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

int n, k, fa[maxn], size[maxn], l[maxn], r[maxn];
char s[maxn];
int get(int x) {return fa[x] == x? x : fa[x] = get(fa[x]);}

void merge(int u, int v) {//带权并查集合并
	u = get(u), v = get(v);
	if(!v) swap(u, v);
	fa[v] = u; 
	if(u) size[u] += size[v];//注意,如果u=0的话不能提供size。若cal函数加个特判倒是可以。
}

int cal(int u) {//计算集合u对应的可以提供最少操作次数的选择
	register int v;
	if(u > k) v = u - k; else v = u + k;
	u = get(u), v = get(v);//v是对立集合
	if(!u || !v) return size[u + v];//其中一个不合法,返回另一个
	return min(size[u], size[v]);//否则可以做选择
}

signed main() {//1~k是选,k+1~2k是不选
	n = read(), k = read();
	scanf("%s", s + 1);
	for(int i = 1; i <= k + k; i++) fa[i] = i;
	for(int i = 1; i <= k; i++) size[i] = 1;//选了的话权值就是1
	for(int i = 1, x, y; i <= k; i++) {
		x = read(); while(x--) {
			y = read(); if(!l[y]) l[y] = i; else r[y] = i;
		}//l是第一个集合,r是第二个集合
	}
	
	int ans = 0;
	for(int i = 1; i <= n; i++) {
		if(!r[i]) {
			register int u = l[i]; if(u) {//如果压根没有对应集合那肯定直接跳过
				ans -= cal(u);
				if(s[i] == '1') fa[get(u)] = 0;//确定对立面不能选
				else fa[get(u + k)] = 0;
				ans += cal(u);
			}
		} else {
			register int u = l[i], v = r[i];
			if(s[i] == '1') {
				if(get(u) != get(v)) {//确定没有建边过
					ans -= cal(u), ans -= cal(v);
					merge(u, v); merge(u + k, v + k);
					ans += cal(u);//两个集合合并了,一个root,直接cal是可以的
				}
			} else {
				if(get(u) != get(v + k)) {
					ans -= cal(u), ans -= cal(v);
					merge(u, v + k), merge(u + k, v);
					ans += cal(u);
				}
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

迎评:)
——End——

发布了158 篇原创文章 · 获赞 23 · 访问量 2万+

Guess you like

Origin blog.csdn.net/qq_43326267/article/details/104173575