【题解】P8683 题解

P8683 题解

思路分析

NN 个加号、 MM 个减号以及 N+M+1N+M+1 个整数凑出的合法后缀表达式。

贪心题。

看到“由 NN 个加号、 MM 个减号以及 N+M+1N+M+1 个整数凑出”这一条件时,我们可以知道,题目要求我们用加减组成结果最大的式子。

看到“后缀表达式”这一条件,我们可以知道,凑出的式子还可以加括号,例如 1 2 + 3 4 - + 等于 (1+2)+(3-4)

显然,结果可以表示为 ABA-BAABB 为整数),如果我们要让结果最大,那么我们就得使得 BB 最小,于是可以取最小的数为 BB 即可。

(注:为什么不用管最小的数的正负?如果最小数为负,那么很好,不减反加。如果是正的,那么刚好符合我们的要求。如果是零,啥事没有。)

接下来,我们就要让 AA 最大。设原式为 (A)(B)(A)-(B)

此时剩下 N+MN + M 个数。由于我们可以随意地添加括号,因此我们可以通过如下方法,使得 AA 为余下的所有数的绝对值之和。

  • 如果数为正数,则既可以添正号,放到 (A)(A) 中,也可以添负号,放到 (B)(B) 中。
  • 如果数为负数,则既可以添负号,放到 (A)(A) 中,也可以添正号,放到 (B)(B) 中。
  • 如果数为零,依照正数负数操作均可

接下来,我们证明:通过 NN 个加号与 M1M-1 个减号,通过上述方式,一定可以让所有数变为其绝对值。

不妨设有 aa 个正数与 bb 个零。则负数个数 c=N+Mabc = N+M-a-b

  • 对负数操作,至少要 N+Mab2\dfrac{N+M-a-b}{2} 个正号,N+Mab2\dfrac{N+M-a-b}{2} 个负号。

  • 对正数操作,至少要 a2\dfrac{a}{2} 个正号,a2\dfrac{a}{2} 个负号。

  • 对零操作,至少要 b2\dfrac{b}{2} 个正号,b2\dfrac{b}{2} 个负号。

  • N+M2±1\dfrac{N+M}{2}\pm1 个正号(有一个非负数可以不用正号),N+M2\dfrac{N+M}{2} 个负号。

按照这种方式操作即可使得所有数变为其绝对值,而不用担心会不会加减号不够用。

于是最后直接排序操作即可。注意特判 M=0M = 0 的情况,这种情况不用找最小的数去减,直接全部相加。

代码

#include <iostream>
#include <algorithm>
#include <numeric> 
#define int long long
using namespace std;
const int N = 2e5 + 10;

int a[N];

signed main()
{
	int n, m;
	cin >> n >> m;
	for(int i = 1;i <= n + m + 1;i++)
	{
		cin >> a[i];
	}
	if(m == 0)
	{
		cout << accumulate(a + 1, a + n + m + 1 + 1, 0) << endl; //求和 
	}
	else
	{
		sort(a + 1, a + n + m + 1 + 1); //排序
		int ans = a[n + m + 1] - a[1]; //最大-最小
		for(int i = 2;i <= n + m;i++)
		{
			ans += abs(a[i]); //绝对值之和
		}
		cout << ans << endl;
	}
    return 0;
}
posted @ 2023-08-11 11:55  邻补角-SSA  阅读(14)  评论(0)    收藏  举报  来源