【贪心】The Enchanted Forest—CF1687A

The Enchanted Forest—CF1687A

Each minute, the followings happen in order.

洛谷的翻译没有翻译出来“in oder”。。。

翻译

这个被称为魔法蘑菇的仙境森林因其上生长的蘑菇而得名。它们可能会产生幻觉,一般应远离接近。

  • 《完全不可信赖的名录记》

Marisa来到了仙境森林采摘蘑菇。

仙境森林可以用X轴上的 n n n个点来表示,编号从 1 1 1 n n n。在Marisa开始之前,她的朋友Patchouli使用魔法探测每个点上初始的蘑菇数量,表示为 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an

Marisa可以在第 0 0 0 分钟时从森林中的任意一个点开始。每分钟,按照以下顺序发生:

  • 她从点 x x x移动到点 y y y ∣ x − y ∣ ≤ 1 |x-y|\le 1 xy1,可能有 y = x y=x y=x)。
  • 她收集点 y y y上的所有蘑菇。
  • 森林中的每个点都会出现一个新的蘑菇。

注意,她不能在第 0 0 0 分钟收集蘑菇。

现在,Marisa想知道在 k k k 分钟后她最多能采摘的蘑菇数量。
输入

每个测试用例包含多个测试案例。第一行包含一个整数 t t t 1 ≤ t ≤ 1 0 4 1\leq t\leq 10^4 1t104)——测试用例的数量。以下是各个测试案例的描述。

每个测试案例的第一行包含两个整数 n n n k k k 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1n2105 1 ≤ k ≤ 1 0 9 1\le k \le 10^9 1k109),分别代表蘑菇位置的数量和Marisa的时间。

每个测试案例的第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109),表示点 1 , 2 , … , n 1,2,\ldots,n 1,2,,n上的初始蘑菇数量。

保证所有测试案例中 n n n 的总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2105
输出

对于每个测试案例,输出Marisa在 k k k 分钟后能够采摘到的最多的蘑菇数量。
注意

测试案例 1:

Marisa可以从 x = 2 x=2 x=2开始。在第一分钟,她从 x = 2 x=2 x=2移动到 x = 1 x=1 x=1并采集了 5 5 5个蘑菇。蘑菇的数量变为 [ 1 , 7 , 2 , 3 , 4 ] [1,7,2,3,4] [1,7,2,3,4]。在第二分钟,她从 x = 1 x=1 x=1移动到 x = 2 x=2 x=2并又采集了 7 7 7个蘑菇。蘑菇的数量变为 [ 2 , 1 , 3 , 4 , 5 ] [2,1,3,4,5] [2,1,3,4,5]。Marisa在 2 2 2分钟后共采摘了 12 12 12个蘑菇。

可以证明,无法采摘更多的蘑菇。

测试案例 2:

这是她可能存在的一个移动路径:

2 → 3 → 2 → 1 → 2 → 3 → 4 → 5 2 \rightarrow 3 \rightarrow 2 \rightarrow 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5 23212345

可以证明,无法采摘更多的蘑菇,最多为 37 37 37个蘑菇。

思路

  • 不能走“回头路”,除非走到头。
  • 消耗一个时间用于移动:既可以向左或向右移动一个单位,也可以原地不动(这也是一种移动)。
  • 根据 k k k n n n 的数据范围,发现“有可能”需要分类讨论。

k   > =   n k~>=~n k >= n,这个时候可以把初始时的所有蘑菇都拿走。另外我们还需要计算可以拿走多少重新生长出来的蘑菇。
我们在这里反向计算。
在这个过程中总共新产生了 n   ∗   k n~*~k n  k 个蘑菇。最终状态剩余的 n n n 堆蘑菇的数量是 1 1 1 ~ n n n 的一个排列(例如 3 , 2 , 1 , 4 , 5 , 6 , 7 , 8 3, 2, 1, 4, 5, 6, 7, 8 3,2,1,4,5,6,7,8),其和为 ( 1   +   n )   ∗   n   /   2 (1~+~n)~*~n~/~2 (1 + n)  n / 2
所以拿走的蘑菇数量为: n   ∗   k   +   ( 1   +   n )   ∗   n   /   2 n~*~k~+~(1~+~n)~*~n~/~2 n  k + (1 + n)  n / 2

k   <   n k~<~n k < n 时,并不难分析,这里不再解释。

C o d e Code Code

#include <bits/stdc++.h>
#define int long long
#define sz(a) ((int)a.size())
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 2e5 + 10;

int n, k;
int a[N];

void solve() {
	cin >> n >> k;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
	}
	
	cout << "        ";
	if (k >= n) { // n个位置能全部走完
		int s = 0;
		for (int i = 1; i <= n; i ++) {
			s += a[i];
		}
		int add = n * k - (1 + n) * n / 2;
		cout << s + add << "\n"; 
	} else { // n个位置不能全部走完
		int res = 0;
		int add = (0 + k - 1) * k / 2;
		int s = 0;
		for (int r = 1; r <= n; r ++) {
			s += a[r];
			if (r >= k + 1) {
				s -= a[r - k];
			}
			if (r >= k) {
				res = max(res, s + add);
			}
		}
		cout << res << "\n";
	}
}

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T = 1;
	cin >> T; cin.get();
	while (T --) solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值