[题解] [JSOI2014] 歌剧表演
题面
题解
我们可以把这些人拆成一些集合, 保证对于一个集合你只知道这个整体, 而无法分辨出哪一部分是哪些人
起初所有人都在一个集合中
我们对于每一次操作, 肯定会有一些人属于同一个集合
那你就可以从这个集合中分辨出这些人来, 把这些人抠出来重新丢进一个集合
最后一个人一个集合的就可以被分辨出来
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <set>
const int N = 100005;
using namespace std;
int n, m, id[N], a[N], ans[N], cnt = 1;
set<int> s[N];
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
bool cmp(int a, int b) { return id[a] < id[b]; }
int main()
{
n = read <int> (), m = read <int> ();
for(int i = 1; i <= n; i++) s[id[i] = 1].insert(i);
int num, last;
for(int t = 1; t <= m; t++)
{
num = read <int> ();
for(int i = 1; i <= num; i++) a[i] = read <int> ();
sort(a + 1, a + num + 1, cmp), a[num + 1] = 0;
last = 1;
for(int i = 2; i <= num + 1; i++)
if(id[a[i]] != id[a[i - 1]])
{
for(int j = last; j < i; j++) s[id[a[j]]].erase(a[j]);
++cnt;
if(s[id[a[last]]].size() == 1 && !ans[*s[id[a[last]]].begin()])
ans[*s[id[a[last]]].begin()] = t;
if(last == i - 1 && !ans[a[last]])
ans[a[last]] = t;
for(int j = last; j < i; j++) s[id[a[j]] = cnt].insert(a[j]);
last = i;
}
}
for(int i = 1; i <= n; i++) printf("%d%c", ans[i], i == n ? '\n' : ' ');
return 0;
}