【题解】P8683 [蓝桥杯 2019 省 B] 后缀表达式

前言(闲唠

这是一道蛮有意思的贪心题。
博主老早之前做过两次这道题,两次都没独立想出来。最近准备特长生考试复习到这道题,可算是基本想出来了,不过依旧很激动(因为之前怎么做的一点印象都没有了……),还是记录一下吧,估计以后还用得着(《第四次》)

正文

题面

Link

给定 N N N 个加号、 M M M 个减号以及 N + M + 1 N+M+1 N+M+1 个整数。
A 1 , A 2 , ⋯   , A N + M + 1 A_1,A_2,\cdots,A_{N+M+1} A1,A2,,AN+M+1,小明想知道在所有由这 N N N 个加号、 M M M 个减号以及 N + M + 1 N+M+1 N+M+1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个。

请你输出这个最大的结果。

思路

首先常规思路来讲,肯定是想优先加大的,再减去小的。

不过看数据范围有负数,而题面中是后缀表达式,这种思路就行不通了。因为有负号时,就有可能相当于是对带括号的加减混合算式拆括号,有负负得正的情况嘛。

那该如何利用这点解决这种情况呢?当然是通过变号,使得减去负数,加上正数啦。那接下来的问题就成了如何具体操作:

注意到,符号数量比数字数量少1,那必定有个数字没法改变符号,我们不妨把最大的数放这个位置。

那对于接下来的数,就想要:

①用加号
正数:加在外面
负数:加在前面有一个负号的括号里

②用负号
正数:减在前面有一个负号的括号里
负数:减在外面

这样,管它加号减号有多少就都可以搞了(好耶!)。但是!搞这样一个负号在括号前面就有一个数只能无符号放在括号最前面。因为是要被带着减去的,就选用最小的。

这样,问题就变为了最大值减最小值再加上其它数的绝对值。

代码实现

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

const int N=300010;
int n,m,a[N];
long long ans=0;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n+m+1;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+n+m+2);
	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]);
		}
	}
	cout<<ans;
	return 0;
}

特判全是加号,排序,然后累加即可,注意long long。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值