洛谷P7725 珍珠帝王蟹 分类讨论

题意

给定\(n\)个op,具有符号\(*\)或者符号\(+\) 权值\(v\)

初始值为0,挑选一种操作顺序使得最终值最大

\[1 \leq n\leq 10^5\\ 2 \leq |v| \leq 10^6 \]

分析

大概思路可以明确就是贪心

容易发现比较特殊且棘手的操作的就是乘上负数和加上负数

  • 如果没用乘上负数的操作,那么加上负数的操作我们肯定希望影响越小越好,这个情况比较简单,只要先加上所有正数然后乘上所有正数然后减去所有负数即可
  • 如果有乘上负数的操作 就需要讨论奇偶,因为我们一定希望结果是正数。
    • 如果乘负数的个数是奇数个,那么要让最后的数是正数,只需要先把所有负数加上,然后用绝对值最小的负数去乘上 当前数。这样当前数就成为了非负数,且有偶数个乘负数操作,接下来贪心即可,把所有正数加上,然后乘上剩下的数
    • 如果乘负数的个数是偶数个,那么应该让所有正数先加上,然后把它乘上负数,然后用绝对值最小的负数去乘上当前数,这样当前数成为了负数,这么做是为了同时最大化加减数的贡献,这时再加上所有的负数,最后再乘上剩下的数即可

这样此题就做完了,大概思路就是让加减数先做,且保持正的性质

代码

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll;


ll rd(){
	ll x;
	scanf("%lld",&x);
	return x;
}

const int MOD = 998244353;

int mul(int a,int b){
	int res = (ll)a * b % MOD;
	if(res < 0) res += MOD;
	return res;
}

void add(int &a,int b){
	a += b;
	if(a >= MOD) a -= MOD;
}

void sub(int &a,int b){
	a -= b;
	if(a < 0) a += MOD;
}

char op[5];

int main(){
	int n = rd();
	vector<int> v1,v2,v3,v4; //+:+,-   *:+,-
   	for(int i = 0;i < n;i++){
		scanf("%s",op);
		int val = rd();
		if(op[0] == '+') {
			if(val > 0) v1.push_back(val);
			else v2.push_back(-val);	
		}
		else {
			if(val > 0) v3.push_back(val);
			else v4.push_back(val);
		}
	}	
	int ans = 0;
	sort(v1.begin(),v1.end());
	sort(v2.begin(),v2.end());
	sort(v3.begin(),v3.end());
	sort(v4.begin(),v4.end());
	if(v4.empty()) {
		for(auto it:v1){
			add(ans,it);
		}
		for(auto it:v3){
			ans = mul(ans,it);
		}
		for(auto it:v2){
			sub(ans,it);			
		}
	}
	else {
		if(v4.size() & 1) {
			for(auto it:v2){
				sub(ans,it);
			}
			ans = mul(ans,v4.back());
			v4.pop_back();
			for(auto it:v1){
				add(ans,it);
			}
			for(auto it:v3){
				ans = mul(ans,it);
			}
			for(auto it:v4){
				ans = mul(ans,it);
			}
		}
		else {
			for(auto it:v1){
				add(ans,it);
			}
			ans = mul(ans,v4.back());
			v4.pop_back();
			for(auto it:v2){
				sub(ans,it);
			}
			for(auto it:v3){
				ans = mul(ans,it);
			}
			for(auto it:v4){
				ans = mul(ans,it);
			}
		}
	}
	cout << ans;		
}