Codeforces Round #616 (Div. 2) E. Prefix Enlightenment 圖論


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;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM