2019年第十届蓝桥杯B组省赛(C++)I题
后缀表达式
传送门
最近做一点蓝桥的题目,我很慌(真),慌的一批。训练一下大脑吧,毕竟最近网课太多加上搞网站,就没怎么敲代码,啊啊啊啊。纠结超慌,不得不写点题目。先开始打算题解直接在网站上面写的,github只给了500M的内存,不忍心,题解还是在CSDN上面写吧。。github写Unity3d等的一些开发内容,打算认真搞AI后经验会在上面写。
有点坑坑,我先开始做的时候用贪心处理的,结果找出一组反例,我内心??what,比如四个减号,一个加号,数据是-1,-2,-3,1,2,3
用贪心处理的话是10,但是答案是12!!我左算右算才得到12的。。脑子转不过来。用后缀表达式处理康康,也叫做逆波兰式,我们可以用如下式子得到最大值:
3 + 2 - (-1 - 1)-(-2)-(-3)
这样算出来的答案就是12了
思路是这样的:
如果没有减号,那我们只能把所有得数字都给加起来输出就行。
如果有减号,我们首先把这个数组先排序,我所得到得最大值其实就是加上一个最大值,减去一个最小值,其余的加绝对值,这是为什么呢?
我们最好的策略就是减去负数,加上正数:
如果只有一个减号,那我们只需要减去最小的数;
如果只有一个加号,那我们得加上那个最大的数;
那么中间的情况我们可以通过添加括号全部实现加上正数的情况;
比如1 2 3 4 5
两个加号,两个减号
那么可以写成5 + 4 + 3 - (1 - 2)
把括号一拆开就是 5 + 4 + 3 - 1 + 2;符合上面的描述
比如-1, -2, 3, 4, 5
三个加号,一个减号
可以写成 5 + 4 + 3 - (-1 - 2);符合上面描述
我们也可以用后缀表达式的过程处理,相当于加括号处理,上述过程和后缀表达式差不多其实=-=
好啦上代码啦,由于没有题目链接,我就直接截图啦~
#include <bits/stdc++.h>
using namespace std;
const int N = 2 * 1e5 + 10;
typedef long long ll;
int a[N];
int main()
{
ll ans = 0;
int n, m;
scanf ("%d%d", &n, &m);
int k = n + m + 1;
for (int i = 0; i < k; i++)
{
scanf ("%d", &a[i]);
}
if (!m)
{
for (int i = 0; i < k; i++)
{
ans += 1ll * a[i];
}
cout << ans << endl;
}
else
{
sort(a, a + k);
ans += a[k - 1];
ans -= a[0];
for (int i = 1; i < k - 1; i++)
{
ans += abs(a[i]);
}
cout << ans << endl;
}
return 0;
}
大家可以自行验证一下~有错误欢迎指正哦