1787: [Ahoi2008]Meet 紧急集合
1776: [Usaco2010 Hol]cowpol 奶牛政坛

1704: [Usaco2007 Mar]Face The Right Way

高橋直樹 posted @ 2013年3月25日 16:25 in BZOJ with tags usaco bzoj , 9250 阅读

http://www.lydsy.com/JudgeOnline/problem.php?id=1704

RunID User Problem Result Memory Time Language Code_Length Submit_Time
375337 Liu_Ts 1704 Accepted 864 kb 428 ms C++ 720 B 2013-03-24 22:31:26

 

题意

给定一个01序列,每次可以将连续的k个数取反。

确定一个k使得,将所有数全变成0的操作次数m最小。

题解

枚举k,O(N)验证,更新答案。

把所有当前为1的反转。

验证时,用一个队列,记录被修改过的点,每次找到对当前枚举点有作用的队列区间,

如果区间长度为奇数,说明该点之前被反转。

 

#include<cstring>
#include<cmath>
#include<cstdio>
#include<climits>
using namespace std;
 
const int N=5001;
 
int b[N],a[N],n,m,k,q[N];
 
 
 
int check(int x)
{
    int l=0,r=1,now=0;
    memcpy(b,a,sizeof(a));
    for(int i=1;i<=n;i++)
    {
        while(l<=r && q[l]<=i-x)  l++;
        if(((r-l+1)&1)) b[i]=1-b[i];
        if(b[i])
            if(i<=n-x+1)
                now++,b[i]=0,q[++r]=i;
            else return INT_MAX;
    }
    return now;
}
 
int main()
{
    scanf("%d",&n);
    int m=INT_MAX;
    for(int i=1;i<=n;i++)
        getchar(),a[i]=getchar()=='B';
    for(int i=1;i<=n;i++)
    {
        int tmp=check(i);
        if(tmp<m)
            m=tmp,k=i;
    }
    printf("%d %d\n",k,m);
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter