JZOJ 3864. 【JSOI2014】歌剧表演

题目

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]);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值