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;
}

 

posted @ 2016-04-14 09:22  Fighting_Heart  阅读(164)  评论(0编辑  收藏  举报