noi.ac #30 思维

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

总代价为 \((|a| + |b|) \times 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;
}
posted @ 2018-09-26 11:24  xayata  阅读(168)  评论(0编辑  收藏  举报