[noi.ac] candy

问题描述

一天,小 D 决定买一些糖果。他决定在两家不同的商店中买糖果,来体验更多的口味。

在每家商店中都有 n 颗糖果,每颗糖果都有一个权值:愉悦度,代表小 D 觉得这种糖果有多好吃。其中,第一家商店中的第 i 颗糖果的愉悦度为 Ai,而第二家商店中的第 i 颗糖果的愉悦度为 Bi。

在每家商店买的糖果会被打包到一个袋子中(可以在一家商店什么都不买,此时认为这家商店的袋子为空)。小 D 回家后,因为这两个袋子外观是一样的,所以他会从两个袋子中随机选择一个.,然后吃光里面的糖果。小 D 定义一种买糖果的方案的愉悦度为:吃到的糖果的愉悦度之和最小可能值

购买每颗糖果的花费均为 W,小 D 想要最大化:买糖果的愉悦度买糖果的花费之差(xy 的差即为 xy),请你帮他求出这个最大值。

输入格式

第一行两个空格隔开的整数 n,W,表示每家商店中的糖果数目以及每颗糖果的花费。

第二行 n 个空格隔开的整数 A1,A2,⋯,An,表示第一家商店中的糖果的愉悦度。

第三行 n 个空格隔开的整数 B1,B2,⋯,Bn,表示第二家商店中的糖果的愉悦度。

保证输入的 {A} 和 {B} 均按照从小到大的顺序排列。

输出格式

输出一行一个整数,表示这个差值的最大值。

样例输入

4 10
12 14 16 19
14 15 20 37

样例输出

5

数据范围

1≤n≤105,1≤Ai,Bi,W≤106。对于任意 1≤i<n,有 Ai≤Ai+1 且 Bi≤Bi+1。

解析

考虑贪心,实际上在每个商店中选择愉悦值尽量大的糖果一定更优。我们设在第一个商店中从大到小选择了(i)个,第二个商店中从大到小选择了(j)个。我们将这两个指针不断向后移动。当一个糖果店的糖果愉悦值之和第一次大于另一家店时,我们移动另一家店的指针,每次统计答案,直到这家店的总和大于另一家店。可以理性证明,此时的答案一定不会更差。

代码

#include <iostream>
#include <cstdio>
#define N 100002
using namespace std;
int n,w,i,j,a[N],b[N];
long long suma,sumb,cnt,ans;
int read()
{
	char c=getchar();
	int w=0;
	while(c<'0'||c>'9') c=getchar();
	while(c<='9'&&c>='0'){
		w=w*10+c-'0';
		c=getchar();
	}
	return w;
}
int main()
{
	n=read();w=read();
	for(i=1;i<=n;i++) a[i]=read();
	for(i=1;i<=n;i++) b[i]=read();
	i=j=n;
	while(i>0||j>0){
		if(suma<sumb){
			if(i==0) break;
			while(i>=1&&suma<=sumb){
				suma+=a[i],cnt++;
				ans=max(ans,min(suma,sumb)-cnt*w);
				i--;
			}
		}
		else{
			if(j==0) break;
			while(j>=1&&sumb<=suma){
				sumb+=b[j],cnt++;
				ans=max(ans,min(suma,sumb)-cnt*w);
				j--;
			}
		}
	}
	printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/LSlzf/p/12305659.html