D. The Enchanted Forest(贪心/逆向思维/数学)

题目

题意:

给定1到n这n个下标位置,这n个下标位置初始时分别有 a i a_i ai个蘑菇。
现在marisa可以选择从这n个位置选择一个做为起始位置,允许采k次蘑菇,并每次采完蘑菇后,可以选择向左、向右或不移动。
每次采完蘑菇后,所有位置都会新增加一个蘑菇。
问marisa采k次蘑菇,最多能采多少蘑菇。
1 < = k < = 1 0 9 , 1 < = n < = 2 ∗ 1 0 5 1<=k<=10^9,1<=n<=2*10^5 1<=k<=109,1<=n<=2105

参考

思路:

我们可以把最终采到的蘑菇分类:原来的蘑菇,以及新增的蘑菇。

当k<=n时

每个位置位置最多只走一次,因此,对于原来的蘑菇,我们只需要取数组 a a a中区间长度为k的子数组中总和最大的那个即可;

对于新增的蘑菇,每个位置都随时间积累而增加,第一个采的位置贡献0个,第二个采的位置贡献1个,… 第k个采的位置贡献k-1个,新增的蘑菇贡献了 1 + 2 + . . . + k − 1 1+2+...+k-1 1+2+...+k1个。
对于原来的蘑菇和新增的蘑菇,它们各自的最优策略不冲突,我们只需要各自计算,最后相加即可。

当k>n时

对于原来的蘑菇,我们可以把它们全部取完,因此贡献了 a 1 + . . . + a n a_1+...+a_n a1+...+an个;

对于新增的蘑菇,我们反向思考,走了k步后,我们有哪些蘑菇是必定取不了、只能舍弃的?当我们走了第 k − i ( 0 < i < n ) k-i(0<i<n) ki(0<i<n)步时,到了点 x i x_i xi,且之后都没经过点 x i x_i xi,而点 x i x_i xi还能产生 i i i个蘑菇(即marisa从第 k − i k-i ki步走到 k k k步),这 i i i个蘑菇是marisa取不了的。换个理解,走了k步后,每个点新增的蘑菇数都为k-1,而这n个点,又分别会剩下一些取不了的点 0 , 1 , . . . , n − 1 0,1,...,n-1 0,1,...,n1个;因此,最终marisa采到的新增蘑菇数为 n − k , n − k − 1 , . . . , n − 1 n-k,n-k-1,...,n-1 nk,nk1,...,n1

同样的,对于原来的蘑菇和新增的蘑菇,它们各自的最优策略不冲突,我们只需要各自计算,最后相加即可。

#include<bits/stdc++.h> 
using namespace std;
#define ll long long
const int maxn = 200010;

int n, k;
ll pre[maxn];
void solve() {
	scanf("%d%d", &n, &k);
	for (int i = 1; i <=n; ++i) {
		scanf("%lld", &pre[i]);
		pre[i] += pre[i-1];
	}
	ll res;
	if (k <= n) {
		res = pre[k];
		for (int i = k+1; i <= n; ++i) {
			res = max(res, pre[i] - pre[i-k]);
		}
		res += (k-1LL)*k/2;
	} else {
		res = pre[n] + (k-1LL + k-n)*n/2;
	}
	printf("%lld\n", res);
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值