noi.ac #30 思维

(des)
给定升序数组 (A, B)
对于任意两个集合 (a, b) 分别是 (A, B) 的子集,总价值为较小的集合的和,

总代价为 ((|a| + |b|) imes w)
最大化的 总价值 - 总代价

(sol)
显然,在升序并且每个元素的代价都相同的条件下集合 (a) 一定是集合 (A)

某个后缀,集合 (b) 同理,因为代价一定的话选价值更高的结果显然更优
这样的话,枚举集合 (A, B) 的每个后缀作为总价值,在另一个集合中找到相应

的最后一个总价值比其大的后缀,统计答案并取更优解

(code)

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

#define LL long long

LL A[N], B[N];
LL n, w;
LL sum1[N], sum2[N];

#define Rep(i, a, b) for(int i = a; i <= b; i ++)

int main() {
	cin >> n >> w;
	Rep(i, 1, n) cin >> A[i];
	Rep(i, 1, n) cin >> B[i];
	reverse(A + 1, A + n + 1);
	reverse(B + 1, B + n + 1);
	Rep(i, 1, n) sum1[i] = sum1[i - 1] + A[i];
	Rep(i, 1, n) sum2[i] = sum2[i - 1] + B[i];
	LL Answer = 0;
	int to = 0;
	Rep(i, 1, n) {
		while(to != n && sum2[to] < sum1[i]) to ++;
		if(sum1[i] > sum2[to]) break;
		Answer = max(Answer, sum1[i] - w * (i + to));
	}
	to = 0;
	Rep(i, 1, n) {
		while(to != n && sum1[to] < sum2[i]) to ++;
		if(sum2[i] > sum1[to]) break;
		Answer = max(Answer, sum2[i] - w * (i + to));
	}
	cout << Answer;
	return 0;
}
原文地址:https://www.cnblogs.com/shandongs1/p/9705886.html