1 条题解
-
0
自动搬运
来自洛谷,原作者为

Delva
**搬运于
2025-08-24 21:43:00,当前版本为作者最后更新于2018-10-23 08:14:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
贪心,枚举,差分
因为同一个点翻转两次就与没有翻转的效果相同了,因此我们有一个贪心策略为:
从左到右对于出现的每一个B翻转一次从当前点开始的区间,就能保证是最优解。
样例的模拟:
如果当前翻转的区间长度为3
粗体表示当前下标
B B F B F B B
(B B F) B F B B
F F B B F B B
F F B B F B B
F F B B F B B
F F (B B F) B B
F F F F B B B
F F F F B B B
F F F F B B B
F F F F (B B B)
F F F F F F F
F F F F F F F
F F F F F F F
但是我们会发现这样是n^2的,再枚举长度,就变为了n^3.因此,需要对区间翻转差分一下,总时间复杂度就是n^2的了
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 10009; int n; bool A[maxn],B[maxn]; int main(){ scanf("%d",&n); char ch; for(int i=1;i<=n;++i){ cin>>ch;A[i]=ch=='B'?0:1; } int mincnt=0x7fffffff,anslen; for(int len=1;len<=n;++len){ memset(B,0,sizeof B); bool b=0,flag=1;int cnt=0;//flag记录当前长度是否有解 for(int i=1;i<=n;++i){//因为区间翻转只有状态0和1,所以用^代替+和- b^=B[i];//数组B为记录差分的数组 if(!(A[i]^b)){//若当前位置为0 if(i+len-1>n){flag=0;break;}//唯一的失败条件:一次翻转的长度大于剩余的长度 b^=1,B[i+len]^=1; ++cnt; } } if(flag){if(cnt<mincnt)mincnt=cnt,anslen=len;} }printf("%d %d\n",anslen, mincnt); }
- 1
信息
- ID
- 1947
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者