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

 

posted @ 2019-08-13 22:45  WeiAR  阅读(168)  评论(0编辑  收藏  举报