zoukankan      html  css  js  c++  java
  • BZOJ2442: [Usaco2011 Open]修剪草坪

    【传送门:BZOJ2442


    简要题意:

      约翰让他的奶牛来修建草坪。他有N 头奶牛,第i 头奶牛的工作能力为Ai。编号相近的奶牛很 熟悉,如果同时让K + 1 头编号连在一起的奶牛工作,她们就会密谋罢工。请问,约翰应该让哪些奶 牛同时工作,使得它们的能力之和最大,而且不会罢工。


    输入格式:

      • 第一行:两个整数N 和K,1 ≤ K ≤ N ≤ 10^5

      • 第二行到N + 1 行:第i + 1 行有一个整数Ai,1 ≤ Ai ≤ 10^9


    输出格式:

      • 单个整数,表示在所有不会罢工的奶牛组合之中,最大的能力之和


    样例输入:

    5 2

    1

    2

    3

    4

    5


    样例输出:

    12


    样例解释:

      除了第三头以外的所有奶牛都工作,总能力 为1 + 2 + 4 + 5 = 12


    题解:

      一开始想到用DP,以为可以AC,结果发现数据范围惊人,想到用单调队列或者斜率优化来搞搞

      想了好久没想出来,后来发现可以转化为每k+1个数就要选一个数,求最小和的经典单调队列例题,求出最小和之后,用所有数的和减去最小和就是这道题的正解了

      尴尬的是,被long long硬是卡了十几分钟......


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    struct node
    {
        LL x;int p;
        node()
        {
            x=0LL;
        }
    }list[110000];
    LL a[110000],f[110000];
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);k++;
        LL s=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            s+=a[i];
        }
        if(n<=k-1)
        {
            printf("%lld
    ",s);
            return 0;
        }
        int head=1,tail=1;
        LL ans=99999999999;
        for(int i=1;i<=n;i++)
        {
            while(head<=tail&&i-list[head].p>k) head++;
            f[i]=list[head].x+a[i];
            while(head<=tail&&f[i]<=list[tail].x) tail--;
            tail++;list[tail].x=f[i];list[tail].p=i;
        }
        for(int i=n-k+1;i<=n;i++) ans=min(ans,f[i]);
        printf("%lld
    ",s-ans);
        return 0;
    }

     

  • 相关阅读:
    【LeetCode-位运算】位1的个数
    【LeetCode-数组】调整数组顺序使奇数位于偶数前面
    mySQL数据库中.frm和.myi和.myd和.ibd文件是什么文件?
    安装docker-compose的两种方式
    将第三方jar包 安装到 maven仓库
    limit分页查询
    pom.xml配置指定仓库
    linux常用命令
    正则笔记
    使用conda创建虚拟环境
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7778476.html
Copyright © 2011-2022 走看看