POJ 3276 Face The Right Way
枚举k,然后计算这个k需要的次数。
从左到右看,如果a[i]是背面的,那么区间[i,i+k-1]需要反转一下,暴力反转效率是o(n*n*n),必然TLE,因此需要优化。
事实上,区间反转的时候可以进行优化,g[i]=1表示区间[i,i+k-1]进行了一次反转,看某个点被反转了几次的时候只需看g[i-k+1]...g[i-1]的和是多少,这个可以用前缀和来进行计算。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const int maxn=5000+10; char op[5]; int a[maxn],n; int g[maxn],sum[maxn]; int ans1,ans2,cnt; void work(int k) { memset(g,0,sizeof g); memset(sum,0,sizeof sum); for(int i=1;i<=n;i++) { if((a[i]+sum[i-1]-sum[i-k])%2==0) { if(i+k-1>n) {cnt=999999999;break;} cnt++; g[i]=1; } sum[i]=sum[i-1]+g[i]; } } int main() { scanf("%d",&n); ans1=1;ans2=0; for(int i=1;i<=n;i++) { scanf("%s",op); if(op[0]=='B') a[i]=0,ans2++; else a[i]=1; } for(int k=2;k<=n;k++) { cnt=0; work(k); if(cnt<ans2) { ans1=k; ans2=cnt; } } printf("%d %d\n",ans1,ans2); return 0; }