蓝桥杯训练——[蓝桥杯][2019年第十届真题]后缀表达式

 三种情况:

(1),负号个数为零,直接全加起来

(2),负号个数小于等于负数个数:

        假设a[1:k]是负数,a[k+1:n+m+1]是正数,m<=k。

       总可以化为 -(a[1]+a[2]+..a[i])-(a[i]+a[i+1]..a[j])-....-(a[z]+a[z+1]...+a[k]);(i<j<z<k);

       这样所有负数都可变为正数,但是有一个特殊,就是所有数都是负数,那么最大的那个负数是不能改变的

(3),负号个数大于负数个数:

      还是(2)的假设的前提下用k-1个负号将k-1个负数变正数,拿出一个负数x来做一个如下组合:

       -(x-a[i]-a[i+1]-...a[j]),其中a[i],a[i+1]...a[j]均为正数,这样就实现了x变为正数,正数还是正数的目的。

      但是有一个特殊情况就是负数个数为0时,x就必须取最小的正数了。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <stack>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef long long ll;
const double eps=1e-6;
ll a[200010];
int main()
{
	IOS;
	ll n,m;
	cin>>n>>m;
	ll cnt=0;//负数个数
	for(int i=1;i<=n+m+1;i++){
		cin>>a[i];
		if(a[i]<0)cnt++;
	}
	sort(a+1,a+1+n+m+1);
	ll ans=0;
	if(m==0){//符号个数为0
		for(int i=1;i<=n+m+1;i++){
			ans+=a[i];
		}
		cout<<ans<<endl;
	}
	else if(cnt>=m){//负数多于负号
		for(int i=1;i<n+m+1;i++){
			ans+=abs(a[i]);
		}
		ans+=a[n+m+1];//这一句防止最大的数是负数的情况
		cout<<ans<<endl;
	}
	else {//负号个数多于负数个数
		for(int i=1;i<=n+m+1;i++){
			ans+=abs(a[i]);
		}
		if(cnt==0){//如果全是正数
			ans-=2*a[1];
		}
		cout<<ans<<endl;
	}
	getchar();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值