连灯-二分

alter-P3718

题意

给定 \(n\) 盏灯的初始状态 \(N/F\),进行最多 \(k\) 次取反,问最短连续状态长度是多少。

思路

写题ing

这题是我自己挑的,所以我知道用什么算法。。。无语。

考虑贪心的话就是每次对最长的连续串的中心取反。思考一下这样子的时间复杂度:优先队列维护最长串,每次取出切一半,放回去两个,不对 \(2/1\) 操作,直到 \(k=0 || pq.empty()\) 似乎是 \(O(nlogn)\) 。试一下。\(1e5\) 不知道 \(pq\) 能不能吃下。

www,贪心不证明,爆零两行泪。为什么??!!

知道了,比如 \(8\)\(N\) ,贪心答案是 \(3\) ,正解是分成 \(5\)\(2\) ,在分 \(5\) 。麻了。

其实真的不是很好想到二分,但好像是有一点感觉的,不是道是不是我知道标签的原因。。

二分最长区间,然后每遍历到一个超过长度的区间就砍,很简单的样子。

还是 \(wa\) 了几个点,这还有什么问题,我贴个 \(check\) 在这

bool chy(int x)
{
    int cnt=0,len=0;
    for(int i=1;s[i];++i)
    {
        ++len;
        if(len>x)
        {
            len=0;
            ++cnt;
        }
        if(s[i]!=s[i+1])
        {
            len=0;
        }
    }
    return cnt<=k;
}

麻了, \(40\) 分钟切不了一道绿题。为什么 \(wa\) 了???

打暴力试一下,反正就是不看题解。再来 \(15\) 分钟。同样判断方法的对拍也是 \(wa\) 的。

算了。我去进食一下,真的不知道错在哪里,就不浪费时间了。

啊啊啊啊,我贪心的时候想到了的,就是哪个不对 \(2\) 操作,啊啊啊啊。对二操作可能会导致下一个连着的变长。。


正文:很容易想到要用二分,然后长度为一要特判,因为对二操作会让下一个长度变长,一特判了就把二分的左边界改为 \(2\)

code

#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn = 1e5+10;
constexpr int INF = 0x3f3f3f3f3f3f3f3f;

int n,k;
char s[maxn];

bool chy(int x)
{
    int cnt=0,len=0;
    for(int i=1;s[i];++i)
    {
        ++len;
        if(len>x)
        {
            ++cnt;
            len=0;
        }
        if(s[i]!=s[i+1])
        {
            len=0;
        }
    }
    return cnt<=k;
}

int binary(int l,int r)
{
    int mid,ret;
    while(l<=r)
    {
        mid=l+((r-l)>>1);
        if(chy(mid))
        {
            ret=mid;
            r=mid-1;
        }
        else
        {
            l=mid+1;
        }
    }
    return ret;
}

char c[3]="FN";

signed main()
{
    #ifndef ONLINE_JUDGE
    freopen("cjdl.in","r",stdin);
    freopen("cjdl.out","w",stdout);
    #endif // ONLINE_JUDGE

    scanf("%lld%lld",&n,&k);
    scanf("%s",s+1);


    int cnt=0;
    for(int i=1;s[i];++i)
    {
        if(s[i]==c[i&1])
        {
            ++cnt;
        }
    }
    if(cnt<=k || n-cnt<=k)
    {
        printf("1\n");
        return 0;
    }

    int ans=binary(2,n/k+2);
    printf("%lld\n",ans);

    return 0;
}
posted @ 2025-11-12 16:28  玖玮  阅读(12)  评论(0)    收藏  举报