[CodeForces950C]Zebras

Description

题目地址: Codeforces

题意:给你一串只含01的字符串,判断能否将字符串分为k个子序列,使得子序列满足以下条件:

  1. 开头和结尾都是0
  2. 相邻的2个数是01或者10

如0, 010, 01010 是合法的,1, 0110, 0101不合法

要求输出方案

(k可以为任意正整数,评测用SPJ)

Solution

我们发现,0可以单独为一组,那么只要匹配完所有的1剩下的0全单独算就行了

对于方案可以用vector储存,关键在于如何划分子序列

开一个指针变量p和一个方案数cnt,p指向一个序列,且保证当前p序列的最后面是0

现在依次考虑每个数字

如果当前数字是0并且p==cnt那么直接新开一个序列,否则把这个0放到p+1的序列中,且++p,这里因为p<cnt所以p+1的序列中必定结尾为1

如果数字是1就把这个1直接放在当前p的序列中,然后p--,这里保证当前序列结尾是0,且p-1的序列结尾是0

简单来说,保证结尾为1的序列全在p的后面,前面(包括p)的序列结尾都是0

方法挺巧妙的,时间复杂度为O(n)

Code

#include <cstdio>
#include <vector>
#include <ctype.h>
using namespace std;

vector<int> Ans[200010];
int p,cnt,n=1;

int main(){
	for(char ch=getchar();isdigit(ch);ch=getchar(),n++)
		if(ch=='1'){
			if(!p){printf("-1\n");return 0;}//1过多的情况
			Ans[p--].push_back(n);
		}else if(p==cnt) Ans[p=++cnt].push_back(n);
		else Ans[++p].push_back(n);
	if(p<cnt){printf("-1\n");return 0;}//0过多的情况
	printf("%d\n",cnt);
	for(int i=1;i<=cnt;++i){
		printf("%d ",Ans[i].size());
		for(int j=0;j<Ans[i].size();++j)
			printf("%d ",Ans[i][j]);
		printf("\n");
	}
	return 0;
}
posted @ 2018-03-09 20:54  void_f  阅读(229)  评论(0编辑  收藏  举报