题意:
给定一个长度为 n n n 且由字符 L , R L,R L,R 构成的字符串,每轮操作中,你都能选择任意对相邻的 R L RL RL ,将其变为 L R LR LR ,询问能否正好用 k k k 轮将字符串中的 L L L 全部移动至左端, R R R 全部移动至右端。
每一轮操作我们都贪心地将所有能够交换的位置互换,统计最少需要 c n t cnt cnt 轮才能完成交换,并统计交换的总次数 s u m sum sum ,如果 k ∈ [ c n t , s u m ] k∈[cnt,sum] k∈[cnt,sum] 那么就可以给出交换方案,因为我们能将某一轮中的操作拆开来,最多能够拆成 s u m sum sum 轮。
AC代码:
const int N = 3010;
vector<int> v[N];
char s[N];
int n, k;
int cnt, sum;
bool flag;
int main()
{
sdd(n, k);
ss(s + 1);
cnt = 0;
sum = 0;
while (1)
{
flag = false;
cnt++;
rep(i, 1, n)
{
if (s[i] == 'R' && s[i + 1] == 'L')
{
flag = true;
v[cnt].pb(i);
}
}
for (auto it : v[cnt])
swap(s[it], s[it + 1]);
sum += v[cnt].size();
if (!flag)
break;
}
cnt--;
if (k < cnt || k > sum)
{
puts("-1");
return 0;
}
rep(i, 1, cnt)
{
while (!v[i].empty() && k > cnt - i + 1)
{
printf("1 %d\n", v[i].back());
v[i].pop_back(); //pop_back()可以删除最后一个元素.
k--;
}
if (!v[i].empty())
{
printf("%d", v[i].size());
for (auto it : v[i])
printf(" %d", it);
printf("\n");
k--;
}
}
return 0;
}