试题 I: 后缀表达式
时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分
【问题描述】
给定 N 个加号、M 个减号以及 N + M + 1 个整数 A 1 ,A 2 ,··· ,A N+M+1 ,小明想知道在所有由这 N 个加号、M 个减号以及 N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
【输入格式】
第一行包含两个整数 N 和 M。
第二行包含 N + M + 1 个整数 A 1 ,A 2 ,··· ,A N+M+1 。
【输出格式】
输出一个整数,代表答案。
【样例输入】
1 1
1 2 3
【样例输出】
4
【评测用例规模与约定】
对于所有评测用例,0 ≤ N, M ≤ 100000,−10^9 ≤ A i ≤ 10^9 。
解题思路:
前言(废话):首先,题目说是后缀表达式,我第一个想到的是用数据结构里栈里的那种后缀表达式的规则去计算,但是题目又说 “求所有由这 N 个加号、M 个减号以及 N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个”,那这样的话 结果和后缀表达式好像没有什么关系啊??。。额…如果只是求它们的最大结果,请看下文:
对于输入的数据,可以分为四种情况:
- 只有“+”号:
此时不论输入的数据是否有负数,只需将所有的输入加起来即可;
例:
input:
0 2
1 2 3
output:
6
说明:1+2+3=6
- 只有负数
此时需要牺牲掉最大负数(即绝对值最小的负数),我也是将所有的数先相加,因为有负数 所以采用绝对值的方式相加。最后结果-最大负数的绝对值*2
例:
input:
1 2
-1 -2 -3 -4
output:
8
说明:
-1-[(-4)+(-3)]-(-2)=-1+4+3+2=8
- 情况3:有"+","-",无负数
此时需要牺牲最小正数,将所有数相加,最后结果-最小正数*2
input:
1 1
1 2 3
output:
4
说明:
3+2-1=4
- 有"+","-",负数
此时,将所有正数和+所有负数绝对值的和即可。
input:
1 2
1 2 3 -4
output:
10
说明:
1-(-4-2)+3=1+4+2+3=10
测试了一些数据,目前还没发现不对的。
代码如下:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
int n,m,i;
int neg=0,pos=0; //负数和正数的个数
int a[200005]={0};
cin>>n>>m;
int len=m+n+1;
for(i=0;i<len;i++){
cin>>a[i];
if(a[i]<0){
neg++; //负数个数
}
else
pos++; //正数个数
}
sort(a,a+len);
//n为"+",m为"-"
long long ans=0;
//情况1:只有 "+"号
if(m==0){
for(i=0;i<len;i++)
ans+=a[i];
}
else{
//情况2:只有负数,pos=0,最后结果-最大负数*2 (牺牲最大负数)
if(pos==0){
for(i=0;i<neg;i++){
ans+=abs(a[i]);
}
ans=ans-abs(a[neg-1])-abs(a[neg-1]);
}
//情况3:有"+","-",无负数,neg=0 (牺牲最小正数)
else if(neg==0){
for(i=0;i<len;i++){
ans+=a[i];
}
ans=ans-a[neg]*2;
}
//情况4:有"+","-",负数 (所有正数和+所有负数绝对值的和)
else{
for(i=0;i<len;i++)
ans+=abs(a[i]);
}
}
cout<<ans<<endl;
return 0;
}