1 条题解
-
0
自动搬运
来自洛谷,原作者为

wangyishan
写不出哪怕一个音符去祭奠你搬运于
2025-08-24 22:41:26,当前版本为作者最后更新于2023-04-03 21:29:04,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P8683 [蓝桥杯 2019 省 B] 后缀表达式 题解
题意简述
-
给定 个加号、 个减号以及 (下文记为 )个整数
-
求由这 个加号、 个减号以及 个整数凑出的合法的后缀表达式中,结果最大的是哪一个。
-
例如输入
1 2 1 2 3,则2 3 + 1 -这个后缀表达式结果是 ,是最大的。
(在这里我们将这 个整数记为 1-idx 的集合 )
题目分析
先上 30pts 代码:
ll ans=0; sort(a+1,a+n+m+1+1); for(int i=1;i<=m;i++)ans-=a[i]; for(int i=m+1;i<=n+m+1;i++)ans+=a[i]; cout<<ans;这是一个明显的贪心思路:先排序,加上 个大数,再减去 个小数。
但是这个贪心能够明显的举出反例:
0 4 1 2 3 4 5答案是 , 他会输出 。因为这是一个后缀表达式,转换到中缀表达式时可能会带着括号!
现在我们的首要目标就是把括号的影响忽略掉。观察上面的例子可以发现,答案 。让我们在举几个例子看看:
- 输入为
0 2 1 2 3,输出为 ; - 输入为
1 2 4 3 2 1,输出为 ; - 输入为
1 2 4 3 -2 -1,输出为 ;
可以看出,
- 在 时答案为 ,
- 而在 时答案为 (此时 数组已经按从小到大排序)
证明:
首先在 时答案一定为所有数的和。
在 时,想让答案最大,那么肯定要多加上大数,减去小数。先把最大的拿出来,放到首项( 个符号, 个数,那么首项一定是正的),把最小的拿出来,放到末项。此时就构成了一个这样的表达式:。
这时其他的数就即可以放到括号外面,又可以放到括号里面。如果是正数括号里就添
-,括号外就添+,负数相反。就这样,我们把所有任意个加号和减号都转变为了绝对值!虽然“牺牲”了最小的值,但是仍然换来了最大的收益。代码
#include<iostream> #include<algorithm> #define ll long long using namespace std; ll a[1000010];int n,m; ll ans=0; int main(){ ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n+m+1;i++) cin>>a[i]; sort(a+1,a+n+m+1+1); if(m==0) for(int i=1;i<=n+m+1;i++) ans+=a[i]; else{ ans=a[n+m+1]-a[1]; for(int i=2;i<=n+m;i++) ans+=abs(a[i]);//abs是c++的库函数 取绝对值 } cout<<ans; return 0; } -
- 1
信息
- ID
- 7030
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者