【第二学期第六周学习记录】

这周写的题并不是很多QAQ;

一道比较有趣的前缀和+二分题:

AT_abc321_d [ABC321D] Set Menu

题目描述

餐厅里有 N N N 个主菜和 M M M 个副菜,第 i i i 个主菜的价格为 A i A_i Ai,第 j j j 个副菜的价格是 B j B_j Bj。餐厅现在要推出一些套餐,每个套餐均由一道主菜和一道副菜组成,对于一个由第 i i i 个主菜和第 j j j 个副菜组成的套餐,我们定义 s = A i + B j s=A_i+B_j s=Ai+Bj,那么这个套餐的价格即为 min ⁡ ( s , P ) \min (s,P) min(s,P) P P P 为一个给定的常数。

请你求出所有可能的套餐的价格总和。


输入格式

第一行三个整数 N , M , P N,M,P N,M,P

第二行 N N N 个整数,表示 A 1 , A 2 … A N A_1,A_2 \dots A_N A1,A2AN

第三行 M M M 个整数,表示 B 1 , B 2 … B N B_1,B_2 \dots B_N B1,B2BN


输出格式

一行一个整数表示答案。

输入输出样例 #1

输入 #1

2 2 7
3 5
6 1

输出 #1

24

输入输出样例 #2

输入 #2

1 3 2
1
1 1 1

输出 #2

6

输入输出样例 #3

输入 #3

7 12 25514963
2436426 24979445 61648772 23690081 33933447 76190629 62703497
11047202 71407775 28894325 31963982 22804784 50968417 30302156 82631932 61735902 80895728 23078537 7723857

输出 #3

2115597124

思路

  • 我们每次用p来二分;
  • 需要注意的是,中间可以用前缀和优化一下,不然可能会超时()

代码

#include <bits/stdc++.h>
using namespace std;
 
const int N=2e5+12;
long long a[N],b[N],s[N];
long long n,m,p;

int search_max(int i)
{
	int l=0,r=m;
	while(l<r){
		int mid=l+r+1>>1;
		if(a[i]+b[mid]<=p)	l=mid;
		else	r=mid-1;
	}
	return l;
} 
int main()
{
	cin>>n>>m>>p;
	for(int i=1;i<=n;i++)	cin>>a[i];
	for(int i=1;i<=m;i++)	cin>>b[i];
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	for(int i=1;i<=m;i++)	s[i]=s[i-1]+b[i];
	long long ans=0;
	for(int i=1;i<=n;i++){
		int r1=search_max(i);
		ans+=p*(m-r1)+r1*a[i]+s[r1];	
	}
	cout<<ans<<"\n";
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值