题意:
有n头奶牛排成一排,有的朝前(F)有的朝后(B),现在你可以使k头奶牛一次性翻转朝向(n>=k>=1),问你最少的翻转次数和此时对应的k值。
Input
Line 1: A single integer: N
Lines 2.. N+1: Line i+1 contains a single character, F or B, indicating whether cow i is facing forward or backward.
Lines 2.. N+1: Line i+1 contains a single character, F or B, indicating whether cow i is facing forward or backward.
Output
Line 1: Two space-separated integers: K and M
Sample Input
7
B
B
F
B
F
B
B
Sample Output
3 3
Analysis
我们先来观察,可以发现,处理好i前面的点后,如果i这个点是B的话,就必须反向,而反向一次以上的话,是无效的(奇数次与1次等效,偶数次于0次等效)。
所以我们可以枚举K,然后从1处理到N,如果需要处理,就再套一个循环修改。这样的复杂度是O(N3),仍然不够。
我们想,如果这个数加上[i-k+1,i-1]的翻转次数,是奇数的话就代表需要切换,然后记录下区间次数和sum每次加上新处理的点,去掉即将在区间外的点。这样,就降到N2 了
Code
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 #include<iostream> 9 #include<algorithm> 10 #define RG register int 11 #define rep(i,a,b) for(RG i=a;i<=b;++i) 12 #define per(i,a,b) for(RG i=a;i>=b;--i) 13 #define ll long long 14 #define inf (1<<29) 15 #define maxn 5005 16 using namespace std; 17 int n,ans1=inf,ans2; 18 int num[maxn],f[maxn]; 19 char s[5]; 20 inline int read() 21 { 22 int x=0,f=1;char c=getchar(); 23 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 24 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 25 return x*f; 26 } 27 28 int main() 29 { 30 n=read(); 31 rep(i,1,n) {scanf("%s",s);if(s[0]=='B') num[i]=1;} 32 rep(k,1,n) 33 { 34 int sum=0,cnt=0;memset(f,0,sizeof(f)); 35 for(RG i=1,lim=n-k+1;i<=lim;++i) 36 { 37 if((num[i]+sum)&1) f[i]=1,cnt++; 38 sum+=f[i];if(i-k>=0)sum-=f[i-k+1]; 39 } 40 rep(i,n-k+2,n) 41 { 42 if((num[i]+sum)&1) 43 { 44 cnt=-1;break; 45 } 46 sum+=f[i];if(i-k>=0)sum-=f[i-k+1]; 47 } 48 if(cnt==-1) continue; 49 if(cnt<ans1) ans1=cnt,ans2=k; 50 } 51 cout<<ans2<<" "<<ans1; 52 return 0; 53 }