题解:首先,交换区间反转的顺序对结果是没有任何影响的,此外,可以知道对于一个区间进行两次以上的反转是多余的。问题被转化成需要被反转的区间的集合,考虑一下最左端的牛,包含这头牛的区间只有一个,因此这头牛面朝前方,就能知道这个区间不需要反转,反之,面向后方,就需要进行反转了,而且在此之后最左的区间不需要反转,这样一来,只需要考虑最左端的牛是否需要反转,问题的规模就缩小了1,不断地重复,就无需搜索就能得出最后的答案了。
可以定义一个数据:f[i]:=区间[i,i+K-1]进行了反转的话为1,否则为0,那么在考虑第i头牛时,如果
所以这个和每一个都可以用常数时间计算出来,复杂度就降为了O(N^2),能在时限内解决了
附上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=5e3+50;
int n;
int dir[MAXN];
int f[MAXN];
int calc(int k)
{
memset(f,0,sizeof(f));
int res=0,sum=0;
for(int i=0;i+k<=n;i++){
if((dir[i]+sum)%2!=0){
res++;
f[i]=1;
}
sum+=f[i];
if(i-k+1>=0){
sum-=f[i-k+1];
}
}
for(int i=n-k+1;i<n;i++){
if((dir[i]+sum)%2!=0){
return -1;
}
if(i-k+1>=0){
sum-=f[i-k+1];
}
}
return res;
}
void solve()
{
int K=1,M=n;
for(int k=1;k<=n;k++){
int m=calc(k);
if(m>=0&&M>m){
M=m;
K=k;
}
}
printf("%d %d\n",K,M);
}
int main()
{
cin>>n;
char c;
for(int i=0;i<n;i++){
cin>>c;
if(c=='B'){
dir[i]=1;
}
}
solve();
return 0;
}