·【蓝桥】·后缀表达式

如果从数字的正负思考该题很容易陷入无比混沌的深渊~

题目链接:·【蓝桥】·后缀表达式

题目分析

  • M+N+1个数,M+N个运算符,运算符只有+号、-号,求结果最大值
    当初天真认为,+运算符从较大的数到较小的开始,-运算符从小到大开始运算,即是最大值
  • 但对于 4 1 -3 -4有运算符+ + -,按这么算是4+1+(-3)-(-4) = 6
    然而 4-(-3+-4)+1 = 12,即-运算符的存在可将+运算符变为-运算符
  • 发现当-运算符存在时,拆掉括号后可将运算符都变为-号(若考虑数字的正、负,容易误入瓶颈,越陷越深)

***结论:
只要存在一个-运算符,后面的运算符都不重要了!因为后面的-运算符都可变为+运算符
注意首项需要放一个数,然后才是-运算符

算法思想

  1. M == 0
    全为+号,输入的数累加即可
  2. M > 0
    存在至少一个-运算符,后面的运算符可全变为+运算符;
    • 于是有了贪心的思想:
      为确保结果最大,ans先加上最大的数,再减去最小的数,剩下的取绝对值,累加(即实现将运算符可全变为+)

***注:
求整个序列求最大值、最小值,排序后代码量会少些

——————————————完整代码————————————————

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <cstdio>
#include <algorithm>
typedef long long ll;
using namespace std;

const int maxn = 2e5+5;
ll a[maxn];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i < m+n+1; ++i){
scanf("%lld", &a[i]);
}
if(m == 0){ //无负号
ll ans = 0;
for(int i = 0; i < m+n+1; ++i){
ans += a[i];
}
printf("%lld\n", ans);
}else{
sort(a, a+m+n+1);
ll ans = a[m+n] - a[0]; //首先最大值-最小值
for(int i = 1; i < m+n; ++i){ //依次取绝对值,累加
ans += abs(a[i]);
}
printf("%lld\n", ans);
}
return 0;
}