【BZOJ5034】【JSOI2014】歌剧表演

【题目链接】

【思路要点】

  • 给每个演员记一种颜色,同色的演员JYY暂时无法分辨。
  • 操作时先对操作集合按颜色排序,分别处理同色的被操作的演员。
  • 对于每一种颜色,将被操作的演员重新染色,与未被操作的演员区分开来,若此时被操作的演员或未被操作的演员个数为一,那么他此时会被JYY认出。
  • 可以用std::set维护同色演员集合,支持加入和删除。
  • 时间复杂度\(O(NLogN)\)(\(N\),\(M\),\(\sum K\)同阶)。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
set <int> num[MAXN];
int n, m, tot;
int col[MAXN], pos[MAXN], ans[MAXN];
bool cmp(int x, int y) {return col[x] < col[y]; }
int main() {
	read(n), read(m);
	tot = 1;
	for (int i = 1; i <= n; i++) {
		col[i] = 1;
		num[1].insert(i);
	}
	for (int i = 1; i <= m; i++) {
		int k; read(k);
		for (int j = 1; j <= k; j++)
			read(pos[j]);
		pos[k + 1] = 0;
		sort(pos + 1, pos + k + 1, cmp);
		for (int j = 1; j <= k; j++) {
			int now = col[pos[j]], from = j;
			while (col[pos[j + 1]] == now) j++;
			int cnt = j - from + 1;
			if (num[now].size() != cnt) {
				tot++;
				for (int l = from; l <= j; l++) {
					int tmp = pos[l];
					col[tmp] = tot;
					num[now].erase(tmp);
					num[tot].insert(tmp);
				}
				if (num[now].size() == 1 && ans[*num[now].begin()] == 0) ans[*num[now].begin()] = i;
				if (num[tot].size() == 1 && ans[*num[tot].begin()] == 0) ans[*num[tot].begin()] = i;
			}
		}
	}
	for (int i = 1; i <= n - 1; i++)
		printf("%d ", ans[i]);
	printf("%d\n", ans[n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80055665
今日推荐