• luogu 2627 修剪草坪


    题目描述

    在一年前赢得了小镇的最佳草坪比赛后,Farm John变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,Farm John希望能够再次夺冠。

    然而,Farm John的草坪非常脏乱,因此,Farm John只能够让他的奶牛来完成这项工作。Farm John有N(1 <= N <= 100,000)只排成一排的奶牛,编号为1...N。每只奶牛的效率是不同的,奶牛i的效率为E_i(0 <= E_i <= 1,000,000,000)。

    靠近的奶牛们很熟悉,因此,如果Farm John安排超过K只连续的奶牛,那么,这些奶牛就会罢工去开派对:)。因此,现在Farm John需要你的帮助,计算FJ可以得到的最大效率,并且该方案中没有连续的超过K只奶牛。

    输入格式

    第一行:空格隔开的两个整数 N 和 K

    第二到 N+1 行:第 i+1 行有一个整数 E_i

    输出格式

    第一行:一个值,表示 Farm John 可以得到的最大的效率值。

    输入输出样例

    输入 #1

    5 2
    1
    2
    3
    4
    5

    输出 #1

    12

    分析

    (1) 记得开long long

    (2) 左闭右开的对列访问队尾要用 r - 1

    (3)将方程变形使其可以用单调队列优化

    (4)当状态不对,空间大了的话,可以尝试将状态下放到每一个元素上

    (5)注意初始状态,初始化,边界条件。比如开始时还没到k时,可以在队列中插入一个0。以免将第一个漏掉(因为转移是用的dp[q[l]][0])其中无法包含第一个

    代码

    /***************************
    User:Mandy.H.Y
    Language:c++
    Problem:luogu2627
    Algorithm:
    Date:2019.8.30 
    ***************************/
    
    #include<bits/stdc++.h>
    #define Max(x,y) ((x) > (y) ? (x) : (y))
    #define Min(x,y) ((x) < (y) ? (x) : (y))
    
    using namespace std;
    
    const int maxn = 1e5 + 5;
    
    int n,k,l,r;
    long long dp[maxn][3];
    long long sum[maxn],q[maxn];
    //dp[第i只牛][是否包含自身] 
    template<class T>inline void read(T &x){
        x = 0;bool flag = 0;char ch = getchar();
        while( ! isdigit(ch)) flag |= ch == '-',ch = getchar();
        while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
        if(flag) x = -x;
    }
    
    template<class T>void putch(const T x){
        if(x > 9) putch(x / 10);
        putchar(x % 10 | 48);
    }
    
    template<class T>void put(const T x){
        if(x < 0) putchar('-'),putch(-x);
        else putch(x);
    }
    
    void file(){
        freopen("testdata.in","r",stdin);
    //    freopen("2627.out","w",stdout);
    }
    
    void readdata(){
        read(n);read(k);
        for(int i = 1;i <= n; ++ i){
            read(sum[i]);
            sum[i] += sum[i-1];
        }
    }
    
    void work(){
        q[r++] = 0;//主要是为了前几个还没到k的考虑
        //因为 dp[q[l]][0] - sum[q[l]]可能小于0 , 
        //所以前面可能出现连加,加上0以免将前几个漏了
        //因为  dp[q[l]][0]不包括自身 
        for(int i = 1;i <= n; ++ i){
        
            while(l < r && q[l] < i-k) l++;
            
            dp[i][0] = Max(dp[i-1][0],dp[i-1][1]);
            if(l < r) dp[i][1] = dp[q[l]][0] - sum[q[l]] + sum[i];
            else dp[i][1] = sum[i] - sum[i-1];
            
            while(l < r && dp[q[r-1]][0] - sum[q[r-1]] <= dp[i][0] - sum[i]) r--;
            //注意是r - 1; 
            
            q[r++] = (long long)i;
        }
        
        put(Max(dp[n][0],dp[n][1]));
    }
    
    int main(){
    //    file();
        readdata();
        work();
        return 0;
    }
    View Code
    非做顽石不可,哪管他敬仰暗唾
  • 相关阅读:
    Spark Executor内存管理
    Spring中Bean的生命周期及其扩展点
    NIO非阻塞IO
    TCP,UDP和socket,Http之间联系和区别
    md5加密,md5加盐加密和解密
    线程监测方法多久没被调用
    项目部署后,替换.class文件不生效
    mysql存储过程导入表
    java生成二维码
    Map中keySet和entrySet的区别
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11433096.html
Copyright © 2020-2023  润新知