【CodeForces - 950C】Zebras
Description
题目地址: Codeforces
题意:给你一串只含01的字符串,判断能否将字符串分为k个子序列,使得子序列满足以下条件:
- 开头和结尾都是0
- 相邻的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[]; int p,cnt,n=; int main(){ for(char ch=getchar();isdigit(ch);ch=getchar(),n++) if(ch=='1'){ if(!p){printf("-1\n");return ;}//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过多的情况 printf("%d\n",cnt); for(int i=;i<=cnt;++i){ printf("%d ",Ans[i].size()); for(int j=;j<Ans[i].size();++j) printf("%d ",Ans[i][j]); printf("\n"); } return ; }