transform (二分+尺取) 牛客

White Cloud placed n containers in sequence on a axes. The i-th container is located at x[i] and there are a[i] number of products in it.
White Rabbit wants to buy some products. The products which are required to be sold must be placed in the same container.
The cost of moving a product from container u to container v is 2*abs(x[u]-x[v]).
White Cloud wants to know the maximum number of products it can sell. The total cost can’t exceed T.
题意: 在数轴上一些位置,以及在该位置上的产品数量,问在运送费用不大于T的情况下,最多能将多少个产品集中在一个位置上?
思路: 首先我们来看一下简化版本,在数轴上的一些位置都分布一个产品,问运输费用最少就能将全部集合在一起,要怎么做,很容易这个位置就是中位数所在的位置
但现在变成位置上的数量不止一个,所以我们应该找到数量的中位数所在的位置才是最佳的,又因为有费用的限制,所以我们可以二分
但是如何check呢?我们可以用尺取,先做左端点,不断枚举又端点查看是否有符合的情况
接下来我们要考虑一些细节问题
首先枚举左右端点形成的区间,左右端点不一定同时全部被运输到中位数所在位置,所以我们要分两种情况,一种就是左端点一定全部被运输,右端点可能有剩,一种就是右端点一定被运输,左端点不一定有剩
我们还要预处理 我们需要在O(1)的时间里算出每段区间运输的费用
sum: 产品数量的前缀和
cost: 将产品运输到位置0的费用钱追回
cal1:将某段区间所有产品运输到位置l的费用
cal2:将某段区间所有产品运输到位置r的费用

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n;
ll T;
int   x[N];
ll    a[N];
ll    sum[N];
ll    cost[N];
ll   cal1(int l,int r)
{
	return cost[r]-cost[l-1]-x[l]*(sum[r]-sum[l-1]);
}

ll  cal2(int l,int r)
{
	return (sum[r]-sum[l-1])*(x[r]-x[l])-cal1(l,r);
}
bool check(ll mid)
{
	int l,r,i;
	ll mid2=mid/2+1;
	l=r=i=1;
	while(1)
	{
		while(r<=n&&sum[r]-sum[l-1]<mid) r++;
		if(r>n) break;
		while(i<=n&&sum[i]-sum[l-1]<mid2) i++;
		//if(i>r) break;
		ll cnt=(sum[r]-sum[l-1]-mid)*(x[r]-x[i]);
		if(cal2(l,i)+cal1(i,r)-cnt <= T) return true;
		l++;
	}
	l=r=i=n;
	while(1)
	{
		while(l>=1&&sum[r]-sum[l-1]<mid)l--;
		if(l<1) break;
		while(i>=1&&sum[r]-sum[l-1]<mid2)i--;
		//if(i<l) break;
		ll cnt=(sum[r]-sum[l-1]-mid)*(x[i]-x[l]);
		if(cal2(l,i)+cal1(i,r)-cnt<= T) return true;
		r--;
	}
	return false;
}
int main()
{
	ll mx=0;
	scanf("%d%lld",&n,&T);
	T>>=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x[i]);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		sum[i]=sum[i-1]+a[i];
		cost[i]=cost[i-1]+a[i]*x[i];
		mx=max(a[i],mx);
	}
	ll l=mx,r=sum[n];
	while(l<=r)
	{
		ll mid=(l+r)>>1;
		if(check(mid))
		{
			l=mid+1;
		}
		else
			r=mid-1;
	}
	printf("%lld\n",r);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值