zoukankan      html  css  js  c++  java
  • 【郑轻】[1895]985的0-1串难题

    1895: 985的0-1串难题

    Time Limit: 1 Sec  Memory Limit:128 MB

    Description

    985有一个长度为n的0-1串,已知他最多可以修改k次(每次修改一个字符即0->1 或者 1->0),他想知道连续的全1子串最长是多少。

    Input

    第一行输入一个整数t,代表有t组测试数据。
    每组数据第一行输入两个整数n,k分别代笔上面的信息。
    注:1 <= t <= 12,1 <= n <= 100000,0 <= k <= 100000。

    Output

    一个整数代表可以得到的最大长度。

    Sample Input

    2
    6 3
    010100
    6 2
    010100
    

    Sample Output

    5
    4
    


    宇神:

    解法一:发现最后的结果是线性的,我们二分答案,把问题变成判定性问题。
    对于当前的二分值mid,判断它的合法性即:是否存在一个mid的连续段使得该段的0字符总数 <= k。
    时间复杂度:O(T * n * log(n))。


    解法二:考虑dp,dp[i]表示以第i个字符开始的最优连续段。
    那么我们只要找到最大的j(i <= j <= n)使得[i, j]里面0字符总数 <= k即可。
    可以先统计0字符的前缀和,然后每次二分即可。最后结果就是max(dp[i]) (1 <= i <= n)。
    时间复杂度:O(T * n * log(n))。


    菜鸡:

    记录0~i之间有多少0保存才cnt[i]中

    则区间[n,m]中有a[m]-a[n-1]个0

    长度(含有字符数)为n-m+1

    所以比较k与a[m]-a[n-1]从而进行区间更新

    并记录出现过的最大长度即为结果


    #include<stdio.h> 
    #include<algorithm> 
    using namespace std; 
    char s[100200]; 
    int cnt[100200]; 
    int main() { 
        int T; 
        scanf("%d",&T); 
        while(T--) { 
            int n,k; 
            scanf("%d %d",&n,&k); 
            scanf("%s",s); 
            cnt[0]=(s[0]=='0'?1:0); 
            for(int i=1; i<n; i++) { 
                cnt[i]=cnt[i-1]; 
                if(s[i]=='0') 
                    cnt[i]++; 
            } 
            if(cnt[n-1]<=k) 
                printf("%d
    ",n); 
            else { 
                int l=0,res=0; 
                for(int i=0; i<n; i++) { 
                    while(k<cnt[i]-(l==0?0:cnt[l-1])) 
                        l++; 
                    res=max(res,i-l+1); 
                } 
                printf("%d
    ",res); 
            } 
        } 
        return 0; 
    } 
    


    题目地址:[1895]985的0-1串难题

  • 相关阅读:
    asp.net web生命周期
    图的数据结构1
    最长公共子串
    内部排序

    棋盘覆盖问题
    队列
    矩阵连乘问题
    图的数据结构2
    旅行售货员问题
  • 原文地址:https://www.cnblogs.com/BoilTask/p/12569432.html
Copyright © 2011-2022 走看看