这周写的题并不是很多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,A2…AN。
第三行 M M M 个整数,表示 B 1 , B 2 … B N B_1,B_2 \dots B_N B1,B2…BN。
输出格式
一行一个整数表示答案。
输入输出样例 #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;
}