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; }
重要的是自信,一旦有了自信,人就会赢得一切。