Codeforces Round #635 (Div. 2)的其他题解请点这里
D. Xenia and Colorful Gems
题目大意:
有三种宝石,分别有n1,n2,n3个
每个宝石有不同的值
每种宝石可以选一个,但是要均衡
使
s
=
(
x
−
y
)
2
+
(
x
−
z
)
2
+
(
y
−
z
)
2
最
小
s=(x-y)^2+(x-z)^2+(y-z)^2最小
s=(x−y)2+(x−z)2+(y−z)2最小
求最小的s
思路:
对于每种宝石,可能出现6种情况
ai <= bi <= ci
ai <= ci <= bi
bi <= ai <= ci
bi <= ci <= ai
ci <= ai <= bi
ci <= bi <= ai
这里我们都看成x y z
对于每种情况,我们可以枚举中间的数y
然后再二分查找 x 和 z
x 是 第一个不小于 y的值 的下标 再减一对应的值
可以用lower_bound
z 是 第一个大于 y的值
可以用upper_bound
然后把上面的6种情况都跑一遍就行了,时间复杂度O(nlogn)
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#include<random>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1e6 + 7;
int n1, n2, n3;
ll p(vector<ll> a,vector<ll> b,vector<ll> c) {
ll x, y, z;
ll minx = 9e18;
for (int i = 0; i < a.size();++i) {
x = a[i];
y = upper_bound(b.begin(),b.end(),x)-b.begin();
z = lower_bound(c.begin(),c.end(),x)-c.begin();
if (y == 0 || z == c.size())continue;
y = b[y-1];z = c[z];
minx = min(minx,
(x - y) * (x - y) + (x - z) * (x - z) + (y - z) * (y - z));
}
return minx;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
vector<ll >a1, a2, a3;
scanf("%d %d %d", &n1, &n2, &n3);
ll x;
for (int i = 1; i <= n1; ++i) {
scanf("%lld", &x);
a1.push_back(x);
}
for (int i = 1; i <= n2; ++i) {
scanf("%lld", &x);
a2.push_back(x);
}
for (int i = 1; i <= n3; ++i) {
scanf("%lld", &x);
a3.push_back(x);
}
sort(a1.begin(), a1.end());
sort(a2.begin(), a2.end());
sort(a3.begin(), a3.end());
ll ans = 9e18;
ans = min(ans, p(a1, a2, a3));
ans = min(ans, p(a1, a3, a2));
ans = min(ans, p(a2, a1, a3));
ans = min(ans, p(a2, a3, a1));
ans = min(ans, p(a3, a1, a2));
ans = min(ans, p(a3, a2, a1));
printf("%lld\n",ans);
}
}