CF1333D Challenges in school №41
链接:https://codeforces.com/contest/1333/problem/D
题意:给定由一个 L、R 组成的长度为 n 的字符串, L、R 表示学生面对当前的方向。如果存在 R 和 L 相邻(即两个学生相向),那么学生可以转向。问能否让学生恰好转动 k 次,输出转向的方案。 ( 1 ≤ n ≤ 3000 , 1 ≤ k ≤ 3 × 1 0 6 ) (1\le n \le 3000 ,1\le k\le 3 \times 10^6) (1≤n≤3000,1≤k≤3×106)
思路:用 vector 存下所有学生一起转向的位置。然后将这些位置拆分成 k 次输出
实现:拆分成 k 次输出时,维护当前已经输出的个数 now。判断当前第 i 行是否输出,只需判断: n o w + 1 + c n t − i + 1 ≤ k now + 1 + cnt - i + 1 \le k now+1+cnt−i+1≤k 。如果满足那么就是可以输出的。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+10;
int n,k;
vector<int> vec[maxn];
string s;
int main()
{
scanf("%d%d",&n,&k);
cin>>s;
s="0"+s;
int cnt=0;
ll sum=0;
while(1)
{
bool valid=false;
cnt++;
for(int i=1;i<n;++i)
{
if(s[i]=='R'&&s[i+1]=='L')
{
vec[cnt].push_back(i);
swap(s[i],s[i+1]);
i++;
valid=true;
}
}
if(!valid)
break;
sum+=vec[cnt].size();
}
if(vec[cnt].size()==0)
cnt--;
if(k<cnt||k>sum)
{
puts("-1");
return 0;
}
for(int i=1;i<=cnt;++i)
{
int p=0,len=vec[i].size();
while(p<len&&k>cnt-i+1)
{
printf("1 %d\n",vec[i][p]);
p++;
k--;
}
if(p<len)
{
printf("%d ",len-p);
for(int j=p;j<len;++j)
printf("%d%c",vec[i][j],j==len-1?'\n':' ');
k--;
}
}
// 写法二
// int now=0;
// for(int i=1; i<=cnt; ++i)
// {
// int m=vec[i].size();
// for(int j=0; j<m; ++j)
// {
// if(j!=m-1)
// {
// if(now+1+cnt-i+1<=k)
// {
// printf("1 %d\n",vec[i][j]);
// now++;
// }
// else
// {
// printf("%d",m-1-j+1);
// while(j<m)
// {
// printf(" %d",vec[i][j]);
// j++;
// }
// puts("");
// now++;
// }
// }
// else printf("1 %d\n",vec[i][j]),now++;
// }
// }
return 0;
}