Codeforces Round #616 (Div. 2) E. Prefix Enlightenment 图论

Stella981
• 阅读 723

E. Prefix Enlightenment

time limit per test3 seconds memory limit per test256 megabytes

There are n lamps on a line, numbered from 1 to n. Each one has an initial state off (0) or on (1).

You're given k subsets A1,…,Ak of {1,2,…,n}, such that the intersection of any three subsets is empty. In other words, for all 1≤i1<i2<i3≤k, Ai1∩Ai2∩Ai3=∅.

In one operation, you can choose one of these k subsets and switch the state of all lamps in it. It is guaranteed that, with the given subsets, it's possible to make all lamps be simultaneously on using this type of operation.

Let mi be the minimum number of operations you have to do in order to make the i first lamps be simultaneously on. Note that there is no condition upon the state of other lamps (between i+1 and n), they can be either off or on.

You have to compute mi for all 1≤i≤n.

Input

The first line contains two integers n and k (1≤n,k≤3⋅105).

The second line contains a binary string of length n, representing the initial state of each lamp (the lamp i is off if si=0, on if si=1).

The description of each one of the k subsets follows, in the following format:

The first line of the description contains a single integer c (1≤c≤n) — the number of elements in the subset.

The second line of the description contains c distinct integers x1,…,xc (1≤xi≤n) — the elements of the subset.

It is guaranteed that:

The intersection of any three subsets is empty; It's possible to make all lamps be simultaneously on using some operations.

Output

You must output n lines. The i-th line should contain a single integer mi — the minimum number of operations required to make the lamps 1 to i be simultaneously on.

Examples

input 7 3 0011100 3 1 4 6 3 3 4 7 2 2 3 output 1 2 3 3 3 3 3 input 8 6 00110011 3 1 3 8 5 1 2 5 6 7 2 6 8 2 3 5 2 4 7 1 2 output 1 1 1 1 1 1 4 4 input 5 3 00011 3 1 2 3 1 4 3 3 4 5 output 1 1 1 1 1 input 19 5 1001001001100000110 2 2 3 2 5 6 2 8 9 5 12 13 14 15 16 1 19 output 0 1 1 1 2 2 2 3 3 3 3 4 4 4 4 4 4 4 5

Note

In the first example:

For i=1, we can just apply one operation on A1, the final states will be 1010110; For i=2, we can apply operations on A1 and A3, the final states will be 1100110; For i≥3, we can apply operations on A1, A2 and A3, the final states will be 1111111. In the second example:

For i≤6, we can just apply one operation on A2, the final states will be 11111101; For i≥7, we can apply operations on A1,A3,A4,A6, the final states will be 11111111.

题意

现在有n个灯泡,初始灯泡可能是开着的,也可能是关着的。

现在有k个开关集合,每个集合控制着c个开关。

现在对应每个前缀1~i,问你最少需要操作多少个集合呢?

以及有两个关键条件:

任意三个开关集合的交集为空,保证有解。

题解

任意三个开关集合的交集为空的意思就是,一个灯泡最多由两个开关集合控制。

把每个开关集合都拆分成两个状态,一个叫做使用,一个叫做不使用。

如果第i个灯泡由第x和第y个开关集合控制,如果i灯泡初始是关着的,那么我缩点x开和y关,缩点x关和y开;同理如果i灯泡初始是开着的,我们缩点x关和y关,x开和y开。然后我选择最小的连体块大小即可。

特殊处理只由1个开关集合控制的灯泡情况。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 6e5+7;
int n,k;
string s;
int l[maxn][2],r[maxn],cnt[maxn];
int getroot(int x){
    return r[x]==x?x:r[x]=getroot(r[x]);
}
int calc(int x){
    int y=x<=k?x+k:x-k;
    x=getroot(x);
    y=getroot(y);
    if(x==0||y==0){
        return cnt[x+y];
    }
    return min(cnt[x],cnt[y]);
}
void fmerge(int x,int y){
    x=getroot(x);
    y=getroot(y);
    if(y==0){
        swap(x,y);
    }
    r[y]=x;
    if(x!=0){
        cnt[x]+=cnt[y];
    }
}
int main(){
    cin>>n>>k;
    cin>>s;
    for(int i=1;i<=k;i++){
        int c;cin>>c;
        for(int j=0;j<c;j++){
            int x;cin>>x;
            if(l[x][0]==0)l[x][0]=i;
            else l[x][1]=i;
        }
        r[i]=i;
        r[i+k]=i+k;
        cnt[i+k]=1;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(l[i][1]==0){
            int x = l[i][0];
            if(x){
                ans-=calc(x);
                if(s[i-1]=='1'){
                    r[getroot(x+k)]=0;
                }else{
                    r[getroot(x)]=0;
                }
                ans+=calc(x);
            }
        }else{
            int x=l[i][0],y=l[i][1];
            if(s[i-1]=='1'){
                if(getroot(x)!=getroot(y)){
                    ans-=calc(x);
                    ans-=calc(y);
                    fmerge(x,y);
                    fmerge(x+k,y+k);
                    ans+=calc(x);
                }
            }else{
                if(getroot(x+k)!=getroot(y)){
                    ans-=calc(x);
                    ans-=calc(y);
                    fmerge(x+k,y);
                    fmerge(x,y+k);
                    ans+=calc(x);
                }
            }
        }
        cout<<ans<<endl;
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
AndroidStudio封装SDK的那些事
<divclass"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2.55,5z"id"raphael
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这