C

智商不够,告辞


看上去毫无头绪。然而打表什么的就能发现一些性质。

我们考虑贪心,(A)(B) 塞在一起排序,发现只要前 (n) 个只要出现属于同一个的,或者都是 (A),或者都是 (B) 就行。

然后构造一发。

不行的情况考虑几个次优不一定合法解,能够证明把几个次优解的答案取个 min 必定会有合法解。

然后暴力判一发。证明很多地方有……菜鸡选手无限偷懒。

#include <bits/stdc++.h>

const int MAXN = 100010;
typedef long long LL;
struct node {
	int v, bel, typ;
	bool operator < (const node & b) const { return v < b.v; }
} ps[MAXN << 1];
int bak;
int A[MAXN], B[MAXN];
int n;
int main() {
	std::ios_base::sync_with_stdio(false), std::cin.tie(0);
	std::cin >> n;
	for (int i = 1; i <= n; ++i) {
		std::cin >> A[i] >> B[i];
		ps[++bak] = (node) {A[i], i, 0};
		ps[++bak] = (node) {B[i], i, 1};
	}
	std::sort(ps + 1, ps + 1 + bak);
	auto solve = [] () {
		static bool app[MAXN][2];
		memset(app, 0, sizeof app);
		int C[2] = {0, 0};
		for (int i = 1; i <= n; ++i) {
			++C[ps[i].typ];
			app[ps[i].bel][ps[i].typ] = true;
		}
		bool can = false;
		for (int i = 1; i <= n; ++i)
			can |= app[i][0] && app[i][1];
		if (can || C[0] == n || C[1] == n) return 
			std::accumulate(ps + 1, ps + 1 + n, 0ll, [] (LL x, node a) {
				return x + a.v;
			});
		return std::numeric_limits<LL>::max();
	};
	LL ans = solve();
	std::swap(ps[n], ps[n + 1]);
	ans = std::min(ans, solve());
	std::swap(ps[n], ps[n + 2]);
	ans = std::min(ans, solve());
	std::swap(ps[n], ps[n + 2]);
	std::swap(ps[n], ps[n + 1]);
	std::swap(ps[n - 1], ps[n + 1]);
	ans = std::min(ans, solve());
	std::cout << ans << std::endl;
	return 0;
}
原文地址:https://www.cnblogs.com/daklqw/p/12098963.html