CF1399D Binary String To Subsequences

23 篇文章 0 订阅
16 篇文章 0 订阅

原题链接:http://codeforces.com/problemset/problem/1399/D

Binary String To Subsequences

You are given a binary string s consisting of n zeros and ones.

Your task is to divide the given string into the minimum number of subsequences in such a way that each character of the string belongs to exactly one subsequence and each subsequence looks like “010101 …” or “101010 …” (i.e. the subsequence should not contain two adjacent zeros or ones).

Recall that a subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, subsequences of “1011101” are “0”, “1”, “11111”, “0111”, “101”, “1001”, but not “000”, “101010” and “11100”.

You have to answer t independent test cases.

Input

The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤2⋅105) — the length of s. The second line of the test case contains n characters ‘0’ and ‘1’ — the string s.

It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output

For each test case, print the answer: in the first line print one integer k (1≤k≤n) — the minimum number of subsequences you can divide the string s to. In the second line print n integers a1,a2,…,an (1≤ai≤k), where ai is the number of subsequence the i-th character of s belongs to.

If there are several answers, you can print any.

Example
input

4
4
0011
6
111111
5
10101
8
01010000

output

2
1 2 2 1
6
1 2 3 4 5 6
1
1 1 1 1 1
4
1 1 1 1 1 2 3 4

题目大意

t t t组询问,每组给出字符串的长度 n n n以及一个长度为 n n n的由 0 0 0 1 1 1组成的二进制字符串。

要求将该二进制字符串分成尽可能少的、相邻字符不相同的子串。输出最少的子串数量以及每个字符所在子串的编号(此处允许存在多解)。

题解

我也不知道这是什么,或许算是一个朴素的贪心 + + +模拟?

显然,对于连续的相同字符,我们不可能将他们划分进同一个子串。

同时,为了使子串的数量最少,我们应该尽可能地把一段连续字符分别接入之前已经有的子串,只有当没有可供接入的子串(即最后一个字符与当前字符不同的子串)时,我们才新建一个以当前字符为结尾,长度为一的新子串。

我们要做的就是模拟上述过程,我们可以用两个桶来分别维护末尾为 0 0 0 1 1 1的子串的编号,接入时将编号从一个桶转移到另一个桶,新建时直接往对应的桶里添加元素。

代码

因为询问有很多组,而我们的数组又因为题目要求得开的比较大,所以重置时不能使用 m e m s e t \mathcal{memset} memset,而应手动清零,否则会 T L E \mathcal{TLE} TLE

(话说这套题的出题人是有多喜欢多组询问啊)

另外退役老咸鱼又重新找回了压行的感觉……

#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5;
int t,n,tot,loc,num;
int buk[M],en[5][M],ans[M];
bool idx;
char bin[M];
void in(){scanf("%d%s",&n,bin);}
void re(){for(int i=0;i<=n;++i)buk[i]=ans[i]=en[0][i]=en[1][i]=0;}
void add(int l,int r){for(int i=l;i<=r;++i)ans[i]=++num,en[idx][++en[idx][0]]=num;}
void link(int l,int r){for(int i=l;i<=r;++i)en[idx][++en[idx][0]]=ans[i]=en[!idx][en[!idx][0]],en[!idx][0]--;}
void ac()
{
	idx=bin[0]-48,tot=1;
	for(int i=0;i<n;++i,++buk[tot])if(idx!=bin[i]-48)++tot,idx=bin[i]-48;
	idx=(bin[0]-48);
	loc=1,num=0;
	for(int i=1;i<=tot;loc+=buk[i],idx^=1,++i)
	if(buk[i]>en[!idx][0])add(loc+en[!idx][0],loc+buk[i]-1),link(loc,loc+en[!idx][0]-1);
	else link(loc,loc+buk[i]-1);
	printf("%d\n",num);
	for(int i=1;i<=n;++i)printf("%d ",ans[i]);putchar(10);
}
int main()
{
	scanf("%d",&t);
	for(int i=1;i<=t;++i)in(),re(),ac();
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值