1521. 魔术卷
原题传送:AcWing 1521. 魔术卷
火星上的魔术商店正在提供一些魔术优惠券。
每个优惠券上都印有一个整数 N N N ,当你将此优惠券用于产品时,商店会给你 N N N 倍于该商品价值的钱。
此外,该商店还免费提供一些赠品。
如果你将印有正整数 N N N 的优惠券用于赠品,你就必须向商店支付 N N N 乘以赠品价值的钱。
但是,神奇的是,他们有一些 N N N 为负数的优惠券!
例如,给定一组优惠券,上面印的数字依次为{1 2 4 -1}
以及一组产品,价值分别为{7 6 -2 -3}
(产品价值为负的是赠品)。
你可以使用第三张优惠券购买第一个产品,得到 28 28 28 元,使用第二张优惠券购买第二个产品,得到 12 12 12 元,使用第四张优惠券购买第四个产品,得到 3 3 3 元。
也就是说,你通过合理使用优惠券,最多可以从商店那里拿走 43 43 43 元钱。
现在,给定你若干的优惠券和若干的商品,每个优惠券和商品最多只能选择一次,请问你最多可以从商店里拿回多少钱。
输入格式
第一行包含一个整数 N c N_c Nc ,表示优惠卷数量。
第二行包含 N c N_c Nc 个整数,表示各优惠券上印有的数值。
第三行包含一个整数 N p N_p Np ,表示产品数量。
第四行包含 N p N_p Np 个整数,表示各产品的价值。
输出格式
输出一个整数,表示最多可以拿回的钱数。
数据范围
1
≤
N
c
,
N
p
≤
1
0
5
1 \le N_c,N_p \le 10^5
1≤Nc,Np≤105 ,
输入的两个整数序列中的元素的绝对值均不超过
100
100
100 。
输入样例:
4
1 2 4 -1
4
7 6 -2 -3
输出样例:
43
思路:
正序将负数和负数配对计算乘积,钱数最多;倒序将正数和正数配对计算乘积,钱数最多;正数和负数的乘积为负数,会使总钱数减少,所以负负加正正为最多的钱数。
题解:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, m, sum = 0;
vector<int> v1, v2, w1, w2;
cin >> n;
while(n--)
{
int x;
cin >> x;
if(x > 0)
v1.push_back(x);
else if(x < 0)
v2.push_back(x);
}
sort(v1.rbegin(), v1.rend());
sort(v2.begin(), v2.end());
cin >> m;
while(m--)
{
int x;
cin >> x;
if(x > 0)
w1.push_back(x);
else if(x < 0)
w2.push_back(x);
}
sort(w1.rbegin(), w1.rend());
sort(w2.begin(), w2.end());
for(int i = 0; i < min(v1.size(), w1.size()); i++)
sum += v1[i] * w1[i];
for(int i = 0; i < min(v2.size(), w2.size()); i++)
sum += v2[i] * w2[i];
cout << sum << endl;
return 0;
}