• 洛谷 P2627 修剪草坪 题解


    P2627 修剪草坪

    题目描述

    在一年前赢得了小镇的最佳草坪比赛后,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

    【思路】

    单调队列 线性DP

    【说在前面的话】

    很有意思的一道题
    正着想那是选择最多的而且区间大小不定
    所以很麻烦对不对
    不想做这道题目了对不对?

    【前缀思路】

    正着不行那就反着来!
    找可以选择的奶牛很麻烦
    那就找出不选的奶牛
    不选的奶牛一定是小的
    而且是不会和别的成一个区间
    因为有两个连续的不选择的奶牛不会让结果更优
    只会让结果更差
    因为多选一个比少选一个会更优的
    具体证明就不多说了
    自己感性理解一下下就好了

    【最终思路】

    然后从第一个点开始枚举
    入队
    如果这队首的到这个点的距离大于了k + 1那就弹出队首
    为什么是k + 1呢
    因为这是不选择的牛
    最长的连续区间是k的长度
    不选择的牛就会在这个区间的两边
    这种情况下是距离k + 1
    并且这种情况是最长情况
    所以是大于k + 1
    然后因为要选择最小的嘛
    那就把队尾大于这个f[i]那也弹出
    因为有了比队尾更小的值那队尾就没有可能会出现了
    比我小还比我强!

    【注意】

    要先弹出队首超出范围的值
    然后再处理出f[i]的值
    最后在弹出队尾的
    因为f[i]的值是取决于前面合法区间内的最小值
    要先把区间内不合法的弹掉
    不然不能保证f[i]合法
    而且弹出的比较依据就是f[i]的大小
    所以先在弹出队尾之前处理出f[i]的值
    这样顺序就出来了吼

    【完整代码】

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define int long long
    using namespace std;
    const int Max = 100005;
    struct node
    {
    	int t;
    	int v;
    };
    deque<node>q;
    int a[Max];
    int f[Max];
    signed main()
    {
    	int n,k;
    	cin >> n >> k;
    	int tot = 0;
    	for(register int i = 1;i <= n;++ i)
    		cin >> a[i],tot += a[i];
    	int M = 0x7f7f7f7f7f7f;
    	q.push_back((node){0,0});
    	for(register int i = 1;i <= n;++ i)
    	{
    		while(!q.empty() && i - q.front().t > k + 1)
    			q.pop_front();
    		f[i] = q.front().v + a[i];
    		while(!q.empty() && f[i] < q.back().v)
    			q.pop_back();
    		q.push_back((node){i,f[i]});
    	}
    	for(register int i = n;i >= n - k;i --)
    		M = min(M,f[i]);
    	cout << tot - M << endl;
    	return 0;
    }
    
  • 相关阅读:
    凸优化-凸函数
    hadoop平台-Hbase安装
    非常实用的python字符串处理方法
    中心极限定理
    线性回归-误差项分析
    nginx为什么性能这么优越?
    Redis为什么单线程还那么快?线程安全吗?
    nginx负载均衡配置
    Dubbo的超时重试机制
    java类加载过程
  • 原文地址:https://www.cnblogs.com/acioi/p/11680772.html
Copyright © 2020-2023  润新知