题意
- 有 \(2N\) 个物品,每个物品有可爱度 \(a_i\) 和颜色 \(c_i\),将其两两配对。假设物体 \(i\) 和 \(j\) 配对,则 \(c_i\neq c_j\),则会增加 \(|a_i-a_j|\) 的不满意度,求最小的不满意度。
分析
- 这道题可以贪心解决。我们尽量让每一对物品颜色相同,令每种颜色的总个数为 \(cnt_c\),则:
- 若 \(cnt_R\)、\(cnt_G\)、\(cnt_B\) 均为偶数,则答案为 \(0\)。
- 若 \(cnt_R\) 和 \(cnt_G\) 为奇数(其余情况同理),那么我们将颜色为 R 和 G 的物品个留出一个配对,剩余的物品以相同颜色两两配对;也可以将一个 R 和一个 B 配对,再把一个 G 和一个 B 配对。取这两种情况的最小值即可。
- 时间复杂度 \(O(n\log n)\)。
AC 代码
#include <bits/stdc++.h>
#define int long long
#define inf 1e18
#define N 200005
using namespace std;
int n;
vector<int> a[4];
inline int read(int &x) {
char ch = x = 0;
while (ch < '0' || ch > '9')
ch = getchar();
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + ch - 48;
ch = getchar();
}
return x;
}
inline int calc(int u, int v) {
int ans = inf;
if (a[v].empty()) {
return ans;
}
int lu = a[u].size(), lv = a[v].size(), j = 0;
for (int i = 0; i < lu; i++) { //求取差值最小的那一对
while (j + 1 < lv && a[v][j + 1] <= a[u][i]) { //尺取法
j++;
}
ans = min(ans, abs(a[u][i] - a[v][j]));
if (j + 1 < lv) {
ans = min(ans, abs(a[u][i] - a[v][j + 1]));
}
}
return ans;
}
signed main() {
read(n);
n <<= 1;
char ch = 0;
int x;
for (int i = 1; i <= n; i++) {
read(x);
ch = getchar();
while (ch < 'A' || ch > 'Z') ch = getchar();
if (ch == 'R') a[1].push_back(x);
else if (ch == 'G') a[2].push_back(x);
else a[3].push_back(x);
}
vector<int> res;
for (int i = 1; i <= 3; i++) {
sort(a[i].begin(), a[i].end());
if (a[i].size() % 2 == 1) {
res.push_back(i);
}
}
if (res.empty()) {
printf("0");
return 0;
}
int u = res[0], v = res[1], w = 6 - u - v;
int uv = calc(u, v);
int uw = calc(u, w);
int vw = calc(v, w);
printf("%lld", min(uv, uw + vw));
return 0;
}
- 感谢观看!留个赞吧~