zoukankan      html  css  js  c++  java
  • P3718 [AHOI2017初中组]alter

    贪心+二分答案

    二分最终答案长度

    主要问题在check上

    ~~我代码写得巨丑,大家还是不要看我的代码了~~

    ------------

    1:当mid大于1的时候,贪心策略是这样的:

    当前连续的长度大于mid时,我不反转最后一个,我也不管它具体反转哪一个,我直接跳过这mid+1个,也就是开始处理i+1。举个例子,
    mid=3,k=1,NNNNNNN,我反转第4个,变成NNNFNNN
    mid=3,k=1,NNNNFFF,我反转前3个的任意一个
    不管怎么反转,前4个对后面是没有影响了,那我就不用管具体怎么反转的


    2:当mid等于1的时候,贪心策略是这样的:

    跑两遍check,反转第一个,或者不反转第一个,两种情况有一个能行就ok

    ------------

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #define inf 2147483647
    #define N 1000010
    #define p(a) putchar(a)
    #define For(i,a,b) for(int i=a;i<=b;++i)
    //by war
    //2019.8.13
    using namespace std;
    int n,k,l,r,mid,a[N],cnt,now;
    char c[N];
    void in(int &x){
        int y=1;char c=getchar();x=0;
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        x*=y;
    }
    void o(int x){
        if(x<0){p('-');x=-x;}
        if(x>9)o(x/10);
        p(x%10+'0');
    }
    
    bool check1(int x,int t){
        int lf=k-1;
        For(i,1,n)
            if(c[i]=='N')
                a[i]=1;
            else
                a[i]=0;
        cnt=1;now=t;
        For(i,2,n){
            if(a[i]==now){
                ++cnt;
                if(cnt>x){
                    a[i]^=1;
                    if(x!=1){
                        now=a[i+1];
                        cnt=0;
                    }
                    else{
                        now=a[i];
                        cnt=1;
                    }
                    if(--lf<0)
                        return 0;
                }
            }
            else{
                now=a[i];
                cnt=1;
            }
        }
        return 1;
    }
    
    bool check(int x){
        int lf=k;
        For(i,1,n)
            if(c[i]=='N')
                a[i]=1;
            else
                a[i]=0;
        cnt=1;now=a[1];
        For(i,2,n){
            if(a[i]==now){
                ++cnt;
                if(cnt>x){
                    a[i]^=1;
                    if(x!=1){
                        now=a[i+1];
                        cnt=0;
                    }
                    else{
                        now=a[i];
                        cnt=1;
                    }
                    if(--lf<0){
                        if(x==1){
                            if(check1(x,a[1]^1))
                                return 1;
                            return 0;
                        }
                        return 0;
                    }
                }
            }
            else{
                now=a[i];
                cnt=1;
            }
        }
        return 1;
    }
    
    signed main(){
        in(n);in(k);
        cin>>(c+1);
        l=1;r=n;
        while(l<r){
            mid=(l+r)>>1;
            if(check(mid))
                r=mid;
            else
                l=mid+1;
        }
        o(l);
        return 0;
    }
  • 相关阅读:
    python中用exit退出程序
    习题5-2 使用函数求奇数和 (15分)
    习题5-1 符号函数 (10分)
    练习5-3 数字金字塔 (15分)
    练习5-2 找两个数中最大者 (10分)
    练习5-1 求m到n之和 (10分)
    ubuntu使用教程
    图解HTTP 上
    Sublime Text 3 插件
    两千行PHP学习笔记
  • 原文地址:https://www.cnblogs.com/war1111/p/11349106.html
Copyright © 2011-2022 走看看