题意 :
- 给一01序列,要求若干次操作后序列整体非严格递增,每次操作可以选一个非严格递减的子序列发生逆序,求最小操作次数
思路 :
- 非严格递增,要变成000…0111…1的形式
- 定义cnt为1的个数,找出最后cnt个数中0的下标和,前n-cnt个数中的1的下标,然后1次操作,既可以让序列整体非严格递增,又满足了非严格递减的子序列,而且是最小操作次数。找出所有所需下标后还要忘了排序
- 特殊地,如果原序列就是00…011…1的形式,最小操作次数为0
#include <iostream>
#include <algorithm>
#include <vector>
#define pb push_back
using namespace std;
const int N = 1010;
int a[N], b[N];
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int _;
cin >> _;
while (_ -- )
{
int n;
cin >> n;
string s;
cin >> s;
for (int i = 1; i <= n; i ++ ) a[i] = s[i - 1] - '0', b[i] = a[i];
sort(b + 1, b + 1 + n);
bool flag = true;
for (int i = 1; i <= n; i ++ )
if (a[i] != b[i])
{
flag = false;
break;
}
if (flag)
{
cout << 0 << endl;
continue;
}
cout << 1 << endl;
vector<int> ve;
int cnt = 0;
for (int i = 1; i <= n; i ++ ) cnt += (a[i] == 1);
for (int i = n; i >= n - cnt + 1; i -- )
if (a[i] == 0)
ve.pb(i);
for (int i = 1; i <= n - cnt; i ++ )
if (a[i] == 1)
ve.pb(i);
sort(ve.begin(), ve.end());
cout << ve.size() << ' ';
for (auto it : ve) cout << it << ' ';
cout << endl;
}
return 0;
}