专栏文章

题解:P14306 【MX-J27-T3】旋律

P14306题解参与者 6已保存评论 6

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
6 条
当前快照
1 份
快照标识符
@miniab61
此快照首次捕获于
2025/12/02 02:52
3 个月前
此快照最后确认于
2025/12/02 02:52
3 个月前
查看原文

观察题目

题目求一段序列的长度乘 kk 减去极差的最大值。
因为不是子串,所以跟元素的位置没有关系。

处理

我们将题目 aa 升序排序,可以证明最后取得的答案实际上是排序后序列的子串,最大值就是右端点元素,最小值就是左端点元素,极差就是右端点的元素减去左端点的元素。
那么所求即为: maxi=1n((ji+1)×k(ajai)))(i<jn)\max\limits_{i = 1}^{n}((j - i + 1) \times k- (a_j - a_i))) (i < j \le n)
此时复杂度 O(n2)O(n^{2})

考虑优化

计算每一位的贡献,发现如果当前已经得到了一个答案,现在加入下一位,那么序列长度加 11, 极差加 aiai1a_i - a_{i - 1},因此对答案的贡献为 k(aiai1)k - (a_i - a_{i - 1})
于是我们可以预处理出每一位的贡献(第 2n2\sim n 位),即为序列 ww,发现我们只需要求 ww 的最大子段和即可。注意一下细节,第一位还有 11 的长度,所以最后答案要加 kk

AC code:

CPP
#include <bits/stdc++.h>
#define REP(i, a, b) for (int i = a; i <= b; i ++)
using namespace std;
const int N = 1e5 + 10;
int a[N], w[N], f[N];
void solve() {
	int n, k; cin >> n >> k;
	int ans = 0;
	REP(i, 1, n) cin >> a[i];
	sort(a + 1, a + 1 + n);
	REP(i, 1, n) w[i] = k - (a[i] - a[i - 1]);
	REP(i, 2, n) f[i] = max(f[i - 1] + w[i], w[i]), ans = max(ans, f[i]);
	cout << ans + k << '\n';
}
signed main(){
//	File("melody");
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int c, T; cin >> c >> T;
	while (T --) solve();
	return 0; 
} 

评论

6 条评论,欢迎与作者交流。

正在加载评论...