[ARC121D]1 or 2

[ARC121D]1 or 2

壹、题目描述 ¶

传送门 to Atcoder.

贰、题解 ¶

考试的时候没看这道题可惜了。

十分显然的结论

\[\forall a\le b\le c\le d,\min\{a+c,b+d\}\le \min\{a+d,b+c\},\max\{a+c,b+d\}\ge \max\{a+d,b+c\} \]

那么显然,最后的答案一定会是贪心地将最大值与最小值加起来,次大值与次小值加起来......

但是有可能有不够配对的情况?考虑只选择一个数字 \(x\) 的情况,实际上就是 \(x+0\),即它与 \(0\) 配对。

考虑到 \(n\le 5000\),我们枚举添加 \(0\) 的数量,\(\mathcal O(n^2)\) 足以解决这个问题。

叁、参考代码 ¶

因为人太懒了,加入一个元素都要再调用一次 \(\tt sort()\),导致这份代码是 \(\mathcal O(n^2\log n)\) 的......

#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;

// #define NDEBUG
#include<cassert>

#define rep(i, l, r) for(int i=(l), i##_end_=(r); i<=i##_end_; ++i)
#define drep(i, l, r) for(int i=(l), i##_end_=(r); i>=i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template<class T>inline T fab(T x){ return x<0? -x: x; }
template<class T>inline T readin(T x){
    x=0; int f=0; char c;
    while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
    for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
    return f? -x: x;
}
template<class T>inline void writc(T x, char s='\n'){
    static int fwri_sta[1005], fwri_ed=0;
    if(x<0) putchar('-'), x=-x;
    do fwri_sta[++fwri_ed]=x%10, x/=10; while(x);
    while(putchar(fwri_sta[fwri_ed--]^48), fwri_ed);
    putchar(s);
}

const int maxn=5000;
const ll inf=1ll<<60;

ll a[maxn*2+5]; int n;

inline void input(){
    n=readin(1);
    rep(i, 1, n) a[i]=readin(1);
}

inline int cmp(ll a, ll b){ return a>b; }

signed main(){
    input();
    int N=n; ll ans=inf;
    rep(i, 0, N){ // enumerate the zero
        ll mx=-inf, mn=inf;
        if(i) a[++n]=0; // pay attention to the special situation
        sort(a+1, a+n+1);
        rep(j, 1, (n>>1)){
            mx=max(mx, a[j]+a[n-j+1]);
            mn=min(mn, a[j]+a[n-j+1]);
        }
        if(n&1) mx=max(mx, a[(n>>1)+1]), mn=min(mn, a[(n>>1)+1]);
        ans=min(ans, mx-mn);
    }
    writc(ans);
    return 0;
}

肆、关键的地方 ¶

可以先想一想贪心地思路,然后再考察能否被证明。

并且,在这里能想到 \(x\)\(x+0\) 这个补项也十分关键。

posted @ 2021-05-31 21:12  Arextre  阅读(73)  评论(2编辑  收藏  举报