BZOJ1704: [Usaco2007 Mar]Face The Right Way 自动转身机
n<=5000个数0或1,每次可以连续对固定长度区间取反,目标把所有1变0,求一个取反区间的固定长度K使取反次数最少。
答案关于K不单调,因此枚举K,对每个K扫一遍区间,遇到1就把连续K个数反转,看最后K-1个数是否在这样一番操作后都为0。为什么?不知道。
区间取反后查询,用差分。n2可过。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<math.h> 6 //#include<iostream> 7 using namespace std; 8 9 int n; 10 #define maxn 5011 11 bool a[maxn],b[maxn]; 12 char c[5]; 13 int main() 14 { 15 scanf("%d",&n); 16 for (int i=1;i<=n;i++) 17 { 18 scanf("%s",c); 19 a[i]=c[0]=='B'; 20 } 21 int ans=n,K=0; 22 for (int k=1;k<=n;k++) 23 { 24 bool now=0;int cnt=0; 25 memset(b,0,sizeof(b)); 26 for (int i=1;i<=n-k+1;i++) 27 { 28 now^=b[i]; 29 if (now^a[i]) 30 { 31 cnt++; 32 now^=1; 33 b[i+k]^=1; 34 } 35 } 36 bool flag=1; 37 for (int i=n-k+2;i<=n;i++) 38 { 39 now^=b[i]; 40 if (a[i]^now) flag=0; 41 } 42 if (flag && cnt<ans) 43 { 44 ans=cnt; 45 K=k; 46 } 47 } 48 printf("%d %d\n",K,ans); 49 return 0; 50 }