题目
思路
想必大家都有一个模糊的思路是,让 max \max max 和 min \min min 匹配。直觉上,这好像是最优的,但是又证明不来。
由于对极差的刻板印象,我往二分的方向想。想了半天啥结果也没有。实在是令人沮丧……
再看看这道题。事实上,上面那玩意儿完全可以证明!其证明也非常简单。考虑
a
≤
b
≤
c
≤
d
a\le b\le c\le d
a≤b≤c≤d 时的两种匹配
⟨
a
,
c
⟩
+
⟨
b
,
d
⟩
\langle a,c\rangle+\langle b,d\rangle
⟨a,c⟩+⟨b,d⟩ 与
⟨
a
,
d
⟩
+
⟨
b
,
c
⟩
\langle a,d\rangle+\langle b,c\rangle
⟨a,d⟩+⟨b,c⟩,你会发现
min
(
a
+
c
,
b
+
d
)
=
a
+
c
≤
min
(
b
+
c
,
a
+
d
)
max
(
a
+
c
,
b
+
d
)
=
b
+
d
≥
max
(
b
+
c
,
a
+
d
)
\min(a+c,b+d)=a+c\le\min(b+c,a+d)\\ \max(a+c,b+d)=b+d\ge\max(b+c,a+d)
min(a+c,b+d)=a+c≤min(b+c,a+d)max(a+c,b+d)=b+d≥max(b+c,a+d)
也就是说,一旦两个数 c , d ( c ≤ d ) c,d\;(c\le d) c,d(c≤d) 所匹配的数字 a , b a,b a,b 也是正序,那么交换会更优。于是 max \max max 只能匹配到 min \min min 去了。
不过上面这是必须两两匹配的情况。还有不匹配怎么办?事实上,不匹配相当于与 0 0 0 匹配。所以枚举一下 0 0 0 的个数即可。
时间复杂度 O ( n 2 ) \mathcal O(n^2) O(n2) 。真是难得的贪心好题啊。
代码
// By DD(XYX)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<map>
#define ll long long
#define MAXN 5005
#define uns unsigned
#define INF 0x7f7f7f7f
#define MOD 998244353ll
#define lowbit(x) ((x)&(-(x)))
using namespace std;
inline ll read(){
ll x=0;bool f=1;char s=getchar();
while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
return f?x:-x;
}
int n,m;
ll a[MAXN],ans=1e18,mn,mx;
vector<ll>g;
int main()
{
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)g.push_back(a[i]);
sort(g.begin(),g.end());
mn=1e18,mx=-1e18;
for(uns i=0,lim=g.size();i<(lim>>1);i++)
mn=min(mn,g[i]+g[lim-i-1]),mx=max(mx,g[i]+g[lim-i-1]);
if(g.size()&1)mn=min(mn,g[g.size()>>1]),mx=max(mx,g[g.size()>>1]);
ans=min(ans,mx-mn);
for(int i=1;i<=n;i++){
g.push_back(0);
for(uns i=g.size()-1;i>0;i--)
if(g[i]<g[i-1])swap(g[i],g[i-1]);
mn=1e18,mx=-1e18;
for(uns i=0,lim=g.size();i<(lim>>1);i++)
mn=min(mn,g[i]+g[lim-i-1]),mx=max(mx,g[i]+g[lim-i-1]);
if(g.size()&1)mn=min(mn,g[g.size()>>1]),mx=max(mx,g[g.size()>>1]);
ans=min(ans,mx-mn);
}
printf("%lld\n",ans);
return 0;
}