Codeforces-1687 A: The Enchanted Forest 【贪心、简单数学】

Codeforces-1687 A: The Enchanted Forest

题目

题目截图

在这里插入图片描述

样例描述

在这里插入图片描述

题目大意

  给定一个长度为 n n n 的数组 { a i } \{a_i\} {ai}
  可以选定数组中的任何位置为初始点,在每一步,以下三个动作顺序发生:
    1. 从当前位置 x x x 移动到位置 y y y。( ∣ x − y ∣ ≤ 1 |x-y| \le 1 xy1,注意可以不动)
    2. 拿走 y y y 位置上的值,加入答案。
    3. 数组上每个位置的值 + 1 +1 +1
  一共可以走 k k k 步,问答案的最大值是多少。

题目解析

  很容易想到,这个题目 k k k n n n 的大小决定了答案走向。
k < = n k <= n k<=n 时,我们不可能往回走,因为在行进的过程中,已经走过的点相当于初始的值已经被拿完了,而新增的值,没走过的值一定大于走过的值,因此,我们直接找整个数组中值和最大的连续一段,顺便再加上新增的值 k ( k − 1 ) / 2 k(k-1)/2 k(k1)/2 即可。
  而 k > n k > n k>n 时,首先能想到的是我们能把初始值拿完,肯定都要拿走,那么之后的问题就是怎样走能够让答案值尽可能的大,换句话说,让走完之后残留的值尽可能的小。我们设当前还有 i i i 步可以走,那么每走一步,我们就会最少有 n − i n-i ni 个浪费值(因为这些加在到不了的 n − i n-i ni 个值上,如果在过程中我们重复移动,那么这个浪费值会更大),那么总的浪费值最小为 ∑ i = 0 n − 1 ( n − i ) = n ( n + 1 ) / 2 \sum_{i=0}^{n-1} (n-i)= n(n+1)/ 2 i=0n1(ni)=n(n+1)/2。因此,我们把过程中总的新增值减去这个数,再加上初始值就是最终答案。
  第二种情况的实例还是很好想的。我们可以从头开始拿完所有初始值,再在尾窝到正好结尾能拿完,然后再走到头,步数正好用完,浪费值也是 n ( n + 1 ) / 2 n(n+1)/2 n(n+1)/2,当然,这只是特例,只要拿完应有的,减少浪费都可以当实例。

Code

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int maxn = 2e5 + 7;
int a[maxn]; LL p[maxn];

int main() {
    int t, n, k;
    cin >> t;
    while(t--) {
        cin >> n >> k;
        for(int i=1; i<=n; ++i) {
            cin >> a[i];
            p[i] = p[i-1] + a[i];
        }
        if(n >= k) {
            LL ans = 0;
            for(int i=k; i<=n; ++i)
                ans = max(ans, p[i] - p[i-k]);
            cout << ans + 1ll * k * (k - 1) / 2 << endl;
        } else {
            LL ans = p[n];
            cout << ans - 1ll * n * (-k * 2  + n + 1) / 2 << endl;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值