zoukankan      html  css  js  c++  java
  • 洛谷P7725 珍珠帝王蟹 分类讨论

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

    题意

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

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

    [1 leq nleq 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;		
    }
    
  • 相关阅读:
    Android应用程序执行流程
    Android的架构与Android应用程序启动流程
    Android开发环境使用工具Eclipse IDE工程目录结构
    MySQL 的 crash-safe 原理解析
    vivo 悟空活动中台
    图解 Promise 实现原理(三)—— Promise 原型方法实现
    领域驱动设计(DDD)实践之路(三):如何设计聚合
    深入浅出开源监控系统Prometheus(上)
    你还应该知道的哈希冲突解决策略
    反应式编程 RxJava 设计原理解析
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15085471.html
Copyright © 2011-2022 走看看