一开始没啥思路,然后往下看,发现是暴力的,但是暴力的非常有技巧。有两个很重要的点
(1)一个区间反转两次是不必要的,就是多余的(因此从头开始,找需要反转的区间,只过一遍就满足)
(2)最重要的是这个,每个区间反转的顺序是不影响最后结果的(所以可以从头开始。直到最后一个区间)
还有就是写的非常有技巧,用了一个类似移动窗口的东西,降低了一维的复杂度
ps:一定要注意边界。从1开始,区间为k,那么最后一个就是n-k+1;
x+k-1=n,所以x=n-k+1。这样好想一点。
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <map> 5 #include <set> 6 #include <algorithm> 7 #include <fstream> 8 #include <cstdio> 9 #include <cmath> 10 #include <stack> 11 #include <queue> 12 using namespace std; 13 const double Pi=3.14159265358979323846; 14 typedef long long ll; 15 const int MAXN=5000+5; 16 const ll mod=1e9+7; 17 18 char b[MAXN]; 19 int a[MAXN]; 20 int f[MAXN]; 21 int n; 22 int C(int k) 23 { 24 memset(f,0,sizeof(f)); 25 int sum=0;int res=0; 26 for(int i=1;i<=n-k+1;i++) 27 { 28 if((a[i]+sum)%2==1) 29 { 30 res++; 31 f[i]=1; 32 } 33 sum+=f[i]; 34 if(i-k+1>=1) 35 sum-=f[i-k+1]; 36 //这个sum用的也是类似尺取法,真的好巧妙 37 } 38 //之后检查剩下的牛,如果还是有向后的,那么就是无解 39 for(int i=n-k+2;i<=n;i++) 40 { 41 if((sum+a[i])%2==1) 42 { 43 return -1; 44 } 45 if(i-k+1>=1) 46 sum-=f[i-k+1]; 47 } 48 return res; 49 } 50 51 int main(){ 52 53 scanf("%d",&n); 54 int minn=n+1; int K=1; 55 56 for(int i=1;i<=n;i++) 57 { 58 cin>>b[i]; 59 if(b[i]=='B') 60 a[i]=1; 61 else a[i]=0; 62 } 63 for(int k=1;k<=n;k++) 64 { 65 int m=C(k); 66 if(m>0&&minn>m) 67 { 68 minn=m; 69 K=k; 70 } 71 } 72 73 printf("%d %d\n",K,minn); 74 return 0; 75 }