1. 程式人生 > 其它 >題解 [ARC121D] 1 or 2

題解 [ARC121D] 1 or 2

詐騙題,竟然評到了 \(2784\) 的驚人高分(快到紅了),來補個題解。

題意:有兩個可重集 \(A,B\)\(B\) 初始為 \(\varnothing\)。每次從 \(A\) 中刪除一個或兩個數,並將它們的和加入 \(B\) 中,重複操作直到 \(A=\varnothing\)。最小化 \(B\) 的極差。

\(1\le |A|\le 5\times 10^3\)

如果每次必須刪除兩個數,顯然最小與最大、次小與次大配對是最優的,可以用交換法證明。觀察到刪除一個數的操作等價於刪除 \(0\) 和那個數。因此列舉有多少次刪除一個數的操作,補充那麼多個 \(0\) 之後跑剛剛的貪心即可。

容易做到 \(\Theta(n^2)\)

,但我懶得做到,所以寫了一個 \(\Theta(n^2\log n)\)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(ll x=(y);x<=(z);x++)
#define per(x,y,z) for(ll x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
const ll N = 1e4+5, inf = 0x3f3f3f3f3f3f3f3fll;

ll n, a[N], b[N], ans = inf;
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}

int main() {
	scanf("%lld", &n);
	rep(i, 1, n) scanf("%lld", &a[i]);
	rep(i, 0, n) {
		ll L = 1, R = n + i;
		if((R - L + 1) & 1) continue;
		rep(j, 1, n) b[j] = a[j];
		rep(j, n+1, n+i) b[j] = 0;
		sort(b+1, b+1+n+i);
		ll mn = inf, mx = -inf;
		while(L < R) {
			chkmin(mn, b[L] + b[R]);
			chkmax(mx, b[L] + b[R]);
			++L; --R;
		}
		chkmin(ans, mx - mn);
	}
	printf("%lld\n", ans);
	return 0;
}