由于没有后台数据,答案不一定正确,仅供参考
问题描述
给定 N 个加号、 M 个减号以及 N + M + 1 个整数 A1; A2; · · · ; AN+M+1,小明想知道在所有由这 N 个加号、 M 个减号以及 N + M + 1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
输入格式
第一行包含两个整数 N 和 M。
第二行包含 N + M + 1 个整数 A1; A2; · · · ; AN+M+1。
输出格式
输出一个整数,代表答案。
样例输入
1 1
1 2 3
样例输出
4
评测用例规模与约定
对于所有评测用例, 0 ≤ N; M ≤ 100000, −109 ≤ Ai ≤ 109。
思路(不一定对,仅供参考)
后缀表达式的运算顺序决定了她是变相可以带上括号的,意味着我们不能够直接最大减最小,比如
0 2
1 2 3
如果直接运算,那么会是 3-1 -2 = 0
但是实际结果是 2 - (1 - 3)= 4
这就需要我们通过改变运算顺序(加括号?)把减法化为加法再直接运算
有n个加号,m个减号
- 假设m是偶数,那么可以转变为m/2个加号
- 如果m是奇数,也可以转换为m/2个加号,只是最后会多出来一个减号,这个减号留给最小的数字即可
根据【 - (a - b) = + (b - a) 】
转换之后我们希望得到大的正数,这个正数的值就是两个数之间的差值,那么每次选取最大 ma x和最小 min 的数,然后做负负得正的变换 -(min - max) = +(max - min) 可以得到一个最大的差值(有点贪心的感觉?),这个变换需要消耗两个减号
- 做 m/2 次上述变换,可以得到一些大的值
- 值得注意的是,每次变换之后得到的大值,应该重新加入数组,作为下一次计算备选的数字之一
- 做完减法变换之后做 n + m / 2 次加法,即可得到结果
代码(仅供参考)
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXLEN 100009
int nums[MAXLEN];
int n, m;
int len;
int main()
{
cin>>n>>m;
len = n + m + 1;
for(int i=0; i<len; i++)
{
cin>>nums[i];
}
sort(nums, nums+len);
// 如果减号刚好能够完全变为加号
if(m%2==0)
{
// 有m/2个新的加号
for(int i=0; i<m/2; i++)
{
int temp = nums[len-1] - nums[0];
nums[0] = temp;
len -= 1;
sort(nums, nums+len);
}
// 加计算
for(int i=0; i<n+m/2; i++)
{
nums[0] += nums[len-1];
len -= 1;
}
cout<<nums[0]<<endl;
}
// 如果减号不能刚刚好变成加号,不对第一个数处理
else
{
for(int i=0; i<m/2; i++)
{
int temp = nums[len-1] - nums[1];
nums[1] = temp;
len -= 1;
sort(nums+1, nums+len);
}
for(int i=0; i<n+m/2; i++)
{
nums[1] += nums[len-1];
len -= 1;
}
// 多出来的一个减号在此运算 ↓
cout<<nums[1]-nums[0]<<endl;
}
return 0;
}