第十届蓝桥杯 I_后缀表达式 【思维】

                              第十届蓝桥杯C/C++_B组 题目汇总   


                                              试题 I: 后缀表达式

                                             时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分
【问题描述】

给定 N 个加号、M 个减号以及 N + M + 1 个整数 A1,A2,··· ,AN+M+1,小 明想知道在所有由这 N 个加号、M 个减号以及 N + M +1 个整数凑出的合法的 后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。 例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
【输入格式】
第一行包含两个整数 N 和 M。 第二行包含 N + M + 1 个整数 A1,A2,··· ,AN+M+1。
【输出格式】
输出一个整数,代表答案。

【样例输入】

1 1

1 2 3
【样例输出】

4

【评测用例规模与约定】

对于所有评测用例,0≤ N,M ≤100000,−109 ≤ Ai ≤109

解题思路

这题很容易想成贪心,即后缀表达式也是表达式,又没有括号,那就尽量加值大的数,减值小的。然而并不是~

后缀表达式实际上是隐藏括号的。 我们可也借助这一特点来变减号为加号。 比如:两个减号,三个数字3 2 1,要是按照前面说的贪心思路来,答案应该是3 - 2 - 1 = 0,即 3 2 - 1 - ,但是如果我们写成, 3 1 2 - -,即3 - (1 - 2) = 3-1+2 = 4,秀不秀??6不6? 明白了这点,我们可以得出结论,假如我们现在有m个减号,那么我们可以把这m个减号变成 k (1<k<=m)个减号,和m-k个加号。

现在有n个加号和m个减号,下面分情况讨论: 

① 负数个数>=m ,因为减去一个负数相当于加上他的绝对值,那么为了得到表达式最大值,我们要减去前m小的负数,剩下的所有数用加法。

//3.31 修改

② 负数个数 ne ∈ [0 , m) ,为了使表达式的值最大,我们应该把这m个减号转化为ne个减号和m-ne个加号,即减去所有负数,加上所有正数。注意最少要保留一个减号,即若没有负数且存在减号,那么要减去一个最小正数。

代码

 

 

代码不对,我懒得改,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

// 3.31 修改 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+5;
ll pnum[maxn],nnum[maxn];	// 存正数和负数 
bool cmp(ll x,ll y)
{
	return abs(x) > abs(y);
}
int main()
{
	int n,m;
	int p=0,ne=0;
	ll t;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n+m+1;i++) {
		scanf("%lld",&t);
		if(t >= 0)
			pnum[++p] = t;
		else
			nnum[++ne] = t; 
	} 
	sort(pnum+1,pnum+p+1,cmp);
	sort(nnum+1,nnum+ne+1,cmp); 
	
	ll ans=0;
	// 当负数个数 >= 减号个数
	if(ne >= m) {
		for(int i=1;i<=m;i++)	// 减去abs前m大的负数 
			ans -= nnum[i];
		for(int i=m+1;i<=ne;i++)	//加上剩下的负数 
			ans += nnum[i]; 
		for(int i=1;i<=p;i++)	// 加上所有正数 
			ans += pnum[i]; 
	} 
	else {	// 负数个数 < 减号个数 
		for(int i=1;i<=ne;i++)	// 减去所有负数 
			ans -= nnum[i];
		for(int i=1;i<=p;i++)	//将多余的减号全部转化为加号, 
			ans += pnum[i]; 
		if(ne == 0)
			ans -= pnum[p]*2; 	//最小的正数加上过一次了,实际上应该减去,所以这里要减去两次 
	} 
	printf("%lld",ans);
} 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值