【JSOI2014】歌剧表演

Description

【JSOI2014】歌剧表演_第1张图片

Solution

本来是一道很简单的题目,没有仔细去想。
如果可以把一个人给认出来,那么就是结合了前面好多次,最后剩下他一个,就把他认出来了。
如果当前表演的是这一坨人,那么考虑给他们染色,记录num表示上一次染得最大的颜色。
染得这一坨人中,在上一轮染色之后,相同颜色的还是一个颜色(说明还不能分辨这两个人),不同颜色的不断的++num,把两个颜色重新区分(因为这一坨人可以跟之前的人区分)。
就这样暴力就好了,可以用链表来实现,也可以打了set。

Code

#include
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=200007;
int i,j,k,l,n,m;
int a[maxn],ans[maxn],num,x;
int bz[maxn],az,d[maxn],b[maxn];
int cz[maxn],c[maxn];
set<int> t[maxn];
int main(){
//  freopen("fan.in","r",stdin);
//  freopen("fan.out","w",stdout);
    scanf("%d%d",&n,&m);
    fo(i,1,n)t[0].insert(i),ans[i]=m+1;
    fo(i,1,m){
        scanf("%d",&k);b[0]=0;
        fo(j,1,k){
            scanf("%d",&x);
            b[++b[0]]=bz[x];
            t[bz[x]].erase(x);
            if(!c[bz[x]])b[++b[0]]=c[bz[x]]=++num;
            t[c[bz[x]]].insert(x);
            bz[x]=c[bz[x]];
        }   
        fo(j,1,b[0]){
            if(t[b[j]].size()==1){
                l=*t[b[j]].begin();
                ans[l]=min(ans[l],i);
            }
        }
        fo(j,1,b[0])c[b[j]]=0;
    }
    fo(i,1,n)if(ans[i]==m+1)ans[i]=0;
    fo(i,1,n)printf("%d ",ans[i]);
}

你可能感兴趣的:(贪心,省选,暴搜)