[思维]The Enchanted Forest Codeforces1688D

Marisa comes to pick mushrooms in the Enchanted Forest.

The Enchanted forest can be represented by nn points on the XX-axis numbered 11 through nn. Before Marisa started, her friend, Patchouli, used magic to detect the initial number of mushroom on each point, represented by a1,a2,…,ana1,a2,…,an.

Marisa can start out at any point in the forest on minute 00. Each minute, the followings happen in order:

  • She moves from point xx to yy (|x−y|≤1|x−y|≤1, possibly y=xy=x).
  • She collects all mushrooms on point yy.
  • A new mushroom appears on each point in the forest.

Note that she cannot collect mushrooms on minute 00.

Now, Marisa wants to know the maximum number of mushrooms she can pick after kk minutes.

Input

Each test contains multiple test cases. The first line contains a single integer tt (1≤t≤1041≤t≤104) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two integers nn, kk (1≤n≤2⋅1051≤n≤2⋅105, 1≤k≤1091≤k≤109) — the number of positions with mushrooms and the time Marisa has, respectively.

The second line of each test case contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) — the initial number of mushrooms on point 1,2,…,n1,2,…,n.

It is guaranteed that the sum of nn over all test cases does not exceed 2⋅1052⋅105.

Output

For each test case, print the maximum number of mushrooms Marisa can pick after kk minutes.

Example

input

4

5 2

5 6 1 2 3

5 7

5 6 1 2 3

1 2

999999

5 70000

1000000000 1000000000 1000000000 1000000000 1000000000

output

12

37

1000000

5000349985

题意: 在一个n格的地图上,有若干蘑菇,每格初始蘑菇数为ai,现在可以任选一个起点,同时可以在k秒内移动,每秒移动一格,移动到某格后可以获得格子内的蘑菇数,同时所有格子蘑菇数增加1,初始时间为0秒,问到k秒时能获得的最大蘑菇数。

分析: 当k <= n时最终答案就是长度为k的最大区间和加上k*(k-1)/2,当k > n时考虑最终状态各个格子上的蘑菇数,因为每秒全图上蘑菇数会增加n,而最终一定可以把全图的蘑菇都走遍,所以只需要计算出浪费的蘑菇数,然后用总蘑菇数一减就是能获得的蘑菇数,而要想浪费的蘑菇数最少就需要最后走到端点,此时每个格子上的蘑菇数为n,n-1,......,3,2,1可以发现其他任何方式浪费的蘑菇数都比这样多,所以可以选择在第一个格子等待,当剩余时间为n-1时一直向右走遍所有格子,这样答案就是sum+n*k-n*(n+1)/2。

这道题如果想到了站在原地不动就会比较简单,但是当时想到的是不断来回移动,虽然答案是一样的,但是实现起来就麻烦一点了。

具体代码如下:

简单版

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#define int long long
using namespace std;

int a[200005];
int c[200005];
const int inf = 0x3f3f3f3f3f3f3f3f;

signed main()
{
	int T;
	cin >> T;
	while(T--){
		int n, k;
		scanf("%lld%lld", &n, &k);
		int sum = 0, mx = -inf;
		for(int i = 1; i <= n; i++){
			scanf("%lld", &a[i]);
			if(i <= k) sum += a[i];
			else sum = sum+a[i]-a[i-k];
			mx = max(mx, sum);
		}
		if(k <= n)
			printf("%lld\n", mx+k*(k-1)/2);
		else
			printf("%lld\n", sum+n*k-n*(n+1)/2);
	} 
	return 0;
}

复杂版

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#define int long long
using namespace std;

int a[200005];
int c[200005];
const int inf = 0x3f3f3f3f3f3f3f3f;

signed main()
{
	int T;
	cin >> T;
	while(T--){
		int n, k;
		scanf("%lld%lld", &n, &k);
		int sum = 0, mx = -inf;
		for(int i = 1; i <= n; i++){
			scanf("%lld", &a[i]);
			if(i <= k) sum += a[i];
			else sum = sum+a[i]-a[i-k];
			mx = max(mx, sum);
			c[i] = c[i-1]+2*i;
		}
		if(n == 1){
			printf("%d\n", a[1]+k-n);
			continue;
		}
		if(k <= n)
			printf("%lld\n", mx+k*(k-1)/2);
		else{ 
			int s = k%(n-1);
			if(s == 0) s = n-1; 
			int t = s*(s-1)/2;
			int path = k-s;
			printf("%lld\n", sum+t+(path/(n-1)-1)*c[n-1]+c[s-1]+(2*s-1+n+s-2)*(n-s)/2);
		}
	} 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值