题解
给题意翻译翻译,其实就是有n个加号,m个减号,n+m+1个数,可以加括号,问组成表达式的最大值。
特殊情况:m=0,直接输出和
一般情况:把所有数排个序,最大的拿出来,放首项,把最小的数拿出来,给他一个减号,再套一个括号,那么现在还未完成的表达式长这样:
可以发现,现在如果我想加一个数的话,给它一个加号,放在括号外面,也可以给它一个减号,放在括号里面;减一个数同理。换句话说,只要用一个减号,一个最大值,一个最小值,其他数我想加就加,想减就减。那么为了使结果最大,我加上正数,减去负数,就是直接加上所有剩下数的绝对值,那么就解决了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e5+10;
int n,m,k;
LL a[2*MAXN];
int main(){
scanf("%d%d",&n,&m);
k=n+m+1;
for(int i=1;i<=k;i++) scanf("%lld",&a[i]);
LL sum=0;
if(!m){
for(int i=1;i<=k;i++) sum+=a[i];
printf("%lld\n",sum);
return 0;
}
sort(a+1,a+k+1);
sum+=a[k];sum-=a[1];m--;
for(int i=2;i<k;i++) sum+=abs(a[i]);
printf("%lld\n",sum);
return 0;
}
借个楼,我再解释清楚一点hh
首先明白这道题为什么叫后缀表达式,是因为后缀表达式不再引用括号(其实是隐式的引用括号),比如2 3 + 1 - 这个式子,就是$ (2 + 3)-1 = 4$, 从左向右计算,不考虑括号,运算符放在两个运算对象之后。
因为符号和数字的顺序可以随便安排,那么可以考虑下面几种情况:
总结一下就是:只要$m > 0$, 那么减号的数量实际上就是1 到$n + m$的任何一个数字。
因此得到下列讨论结果:
太棒了吧!!!!
hh 这个我也想了很久也参考了很多题解
那如果负数比负号多呢?剩下的负数就不能直接加绝对值了啊(是真的不懂不是杠
没太明白你的意思,只要负号的个数大于等于
1
,那么它就可以当n + m
个负号用呀。太强了 思路一下理清了 这题我要碰到估计想不到这么细。。。哎
一语道破
nbnb 思考了很久也没思考出负数比减号多的情况怎么处理,看了这个才明白,只要有减号,总可以把所有负数变成正数
太厉害了
%%% 写的太好啦
大佬!比如,数字是(-1,-2,-3)一个加号一个减号。那么最大是 -1 +( -( - 3 - 1))这样吗。括号可以多加噢?
太细了,牛!
🐂
-1-((-2)+(-3))不是说能多加括号,是能通过调整后缀表达式位置来等价于加上了括号
感谢!!
呢就把+放括号里,即-(+),里面这个正好一展开就起到了-的作用
这么优秀的人居然睡在我的旁边
👀
只要有一个负号,就可以造1~M+N个负号,这1~M+N个负号可以决定1~M+N-1个数字是正数还是负数,那么在输入的数据有正有负时且至少有一个负号就能把所有负数变为正数即可得到最大和(所以求最大值是左边的负数取反+正数),输入数据全为正时且至少有一个负号,减去最小的正数即可得到最大值(故要减去排序后最左边的数),全为负数时,可以把N+M-1个数都转为正数,这些数的绝对值要大,故对排序后靠近左边界的数取反,加上右边界就是最大值(那么求最大值时就相当于减去最左边的数加中间的数的绝对值+最右边的数),这三种情况都要对左边界进行减法,对右边界进行加法,中间数取绝对值
讲的太好了
其实就是-号可以通过
-
负数转成+
号,最终就是等同于最大数减去最小数 再加上剩余所有数的绝对值如何转换的呢?为什么可以呢?
如果全是负数,减号 呢?
看懂了,大佬
太赞了!orz
请问题目哪里的信息告诉我们可以加括号?(本人小白)
后缀表达式转为中缀表达式,相当于加括号,实际后缀表达式没有括号,中缀表达式可以有括号
姨,熟人?
hh,也是财大的嘛
看了这么多 就这个最明白
通俗易懂!orz
66666666
很有道理
大佬太强了!
6666
优秀的人儿
大佬 ,tqi
赞