http://codeforces.com/contest/1399/problem/D
给出一个长度为n的0、1组成的字符串,分为k个子字符串,使得每个子串没有连续的0、1,求k的最小值和子串的所属编号
使用两个队列q0,q1分别存储0和1的下标(同时两个队列的长度之差也体现了0和1的数量差),遍历字符串:遇见’0’时,若s1为空则必须开辟一个新的子序列来存储这个多出来的’0’,若s1不为空,它就直接放到上一个1所在的子序列的后面,也就是子序列编号相同。遇见’1’时同理
#include<iostream>
#include<string>
#include<math.h>
#include<algorithm>
#include<queue>
typedef long long ll;
ll gcd(ll a, ll b)
{
return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
return a* b / (gcd(a, b));
}
#define PII pair<int,int>
using namespace std;
const int N = 1e5 + 5, mod = 1e9 + 7;
int qmi(int a, int k, int p) //快速幂模板
{
int res = 1;
while (k)
{
if (k & 1) res = (ll)res * a % p;
k >>= 1;
a = (ll)a * a % p;
}
return res;
}
///
int a[N];
int pos[N];//记录路径
int main()
{
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
string s;
cin >> s;
queue<int> q0, q1;
memset(pos, 0, sizeof(pos));
int ans = 0;
for (int i = 0; i < n; i++) {
if (s[i] == '0') {
if (q1.empty()) {//暂时没有1结尾的字串
q0.push(ans);
pos[i] = ans;
ans++;
}
else {//有1结尾的字串
pos[i] = q1.front();
q1.pop();
q0.push(pos[i]);//此字串结尾变为0,放到q0中,并且储存位置
}
}
else {
if (q0.empty()) {
q1.push(ans);
pos[i] = ans;
ans++;
}
else {
pos[i] = q0.front();
q0.pop();
q1.push(pos[i]);
}
}
}
cout << ans << endl;
for (int i = 0; i < n; i++)
cout << pos[i] + 1 << " ";
cout << endl;
}
return 0;
}
菜是原罪,不看题解想不出来用队列