• POJ 3276 Face The Right Way(前缀和优化)


    题意:有长度为N的01串,有一个操作可以选择连续K个数字取反,求最小的操作数和最小的K使得最后变成全1串.(N<=5000)

    由于K是不定的,无法高斯消元。

    考虑枚举K,求出最小的操作数。

    显然同样的区间操作两次是没必要的,且区间长度是一定的。从左到右依次考虑每个左端点i。如果为0,则需要改变区间[i,i+K-1].

    此外,还需要考虑之前的操作对这个端点的影响。

    复杂度O(n^3).

    令f[i]为区间左端点为i时是否操作,那么可以发现我们考虑一个端点是否该取反时,前面影响它的是一个连续的区间。前缀和维护即可。

    复杂度O(n^2).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=5005;
    //Code begin...
    
    char temp[3];
    int sum[N], s[N];
    
    int main ()
    {
        int n, cnt, ansx=INF, ansy;
        scanf("%d",&n);
        FOR(i,1,n) scanf("%s",temp), s[i]=(temp[0]=='B');
        FOR(i,1,n) {
            mem(sum,0);
            cnt=0;
            FOR(j,1,n) {
                int z=s[j]+(sum[j-1]-sum[j>=i?j-i:0]);
                if (z&1) {
                    ++cnt;
                    if (j>n-i+1) {cnt=INF; break;}
                    sum[j]=sum[j-1]+1;
                }
                else sum[j]=sum[j-1];
            }
            if (ansx>cnt) ansx=cnt, ansy=i;
        }
        printf("%d %d
    ",ansy,ansx);
        return 0;
    }
    View Code
  • 相关阅读:
    windowswindows/windowslinux间文件远程传输
    GNUstep ObjectC Ubuntu
    Linux日常问题处理集
    上网实用技巧
    ubuntu host VirtualBox xp guest networking
    平衡组/递归匹配
    Linux在线词典
    正则表达式的构造摘要
    Microsoft .NET Pet Shop 4 架构与技术分析
    ASP.net 2.0资料吐血收藏(^_^) (转)
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6345027.html
Copyright © 2020-2023  润新知