题目
Description
Input
Output
Sample Input
输入1:
5 3
3 1 2 3
3 2 3 1
2 1 3
输入2:
4 3
1 1
1 3
1 2
Sample Output
输出1:
0 3 0 0 0
输出2:
1 3 2 3
Data Constraint
题解
将所有演员看一个大集合,
每表演一场就将其中的演员从各自所在的集合中分离出来,然后本来在一个集合的演员表演完后仍在同一个集合。
维护集合的元素数量和产生该集合的时间。
如果该集合的元素个数为1,相应的答案就是产生该集合的时间。
比如说一开始有5个人,集合为{1,2,3,4,5}。
第一场1,2表演,那么1,2从原集合中分离出来,变成{1,2},{3,4,5}仍是一个集合。
第二场2,3表演,那么2,3分别从{1,2},{3,4,5}中分离出来,总共有4个集合{1},{2},{3,5},{4}.
这道题也挺考选手代码实现能力的,有一些十分麻烦的处理一定要打得很优美。
虽然我打的不优美,但我还是过了。
总之,越优美越好。
#include<iostream>
#include<cstdio>
#include<cmath>
#define N 100003
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int ans[N],sz[N*2],f[N],sj[N*2],next[N*2][2],tj[N],last[N],wz;
int bz[N];
int i,j,k,l,n,m,t,x,tot,cnt;
int main()
{
scanf("%d%d",&n,&m);
tot=1;fo(i,1,n) f[i]=tot;
sz[tot]=n;
fo(i,1,m)
{
scanf("%d",&k);
fo(j,1,k)
{
scanf("%d",&x);
if (bz[f[x]]!=i)
{
bz[f[x]]=i;
last[f[x]]=sz[f[x]];
}
sz[f[x]]--;
if (!sz[f[x]]) sj[f[x]]=-sj[f[x]];
if (!next[f[x]][0] || next[f[x]][1]!=i)
{
tot++;
next[f[x]][0]=tot;
next[f[x]][1]=i;
}
if (sj[f[x]]>-1) sj[f[x]]=i;
sz[next[f[x]][0]]++;
wz=f[x];
f[x]=next[f[x]][0];
if (sj[f[x]]>-1) sj[f[x]]=i;
if (!sz[wz] && sz[f[x]]==last[wz]) sj[f[x]]=-sj[wz];
}
}
fo(i,1,n) tj[f[i]]=i;
fo(i,1,tot) if (sz[i]==1) ans[tj[i]]=sj[i];
fo(i,1,n) printf("%d ",ans[i]);
}