Codeforces Round #508 (Div. 2) D. Slime

D. Slime

题目链接:https://codeforces.com/contest/1038/problem/D

题意:

给出两个数,然后每次可以对相邻的两个数合并,比如x,y,那么合并过后就是x-y或者y-x,这里怎么去减是自己决定的。问怎么合并,最后得到的那个数最大。

题解:

这题主要关键就是发现,最后的式子呈现出来的状态,+、-这两个符号一定是两者都有的,至少存在一个(只有一个数时除外),并且状态覆盖了+、-所有的排列。

发现这个性质过后,贪心解一下就行了。我的做法就是模拟的方法,首先将所有正数取完,然后减去所有负数,当然注意对一些边界条件的判断。

但还有更为机智的做法,就是首先将所有数的绝对值加在一起,然后根据式子中最大值、最小值来确定答案。

如果最大值小于0,就应该把答案减去最大值的两倍;如果最小值大于0,就应该把答案加上最小值的两倍;另外的情况不用管了。

我给出我的代码吧:

#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
const int N = 500005;
int n;
ll a[N];
priority_queue <pair<ll,int> > q;
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        q.push(mp(a[i],i));
    }
    if(n==1){
        cout<<a[1];
        return 0;
    }
    int cnt = 0;
    ll ans = 0;
    while(!q.empty()){
        pair<ll,int> now=q.top();
        //cout<<now.first<<" "<<now.second<<endl;
        if(now.first>=0){ 
            cnt++;q.pop();
            if(q.empty()) ans-=now.first;
            else ans+=now.first;
        }else{
            if(cnt==0) ans+=now.first,q.pop();
            break ;
        }
    }
    while(!q.empty()){
        pair<ll,int> now=q.top();q.pop();
        ans-=now.first;
    }
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/10507293.html