CF1336B Xenia and Colorful Gems 题解
UPD:分析了时间复杂度。修正了笔误(我太弱了把大于写成了小于……)
CF1336B Xenia and Colorful Gems
首先,很显然,要让
于是我们考虑,枚举其中一种宝石的所有重量,然后在另外两种宝石的重量中找到最接近它的值,最后找到最小的答案。
为了便于枚举所有情况,我们可以确定下
举个栗子:当我们令
但是由于
当然,不管是用双指针还是二分都要先排序。
由于要多次用到相同的计算,不妨把枚举和计算的过程放到函数里。然后记得开 long long。
我的做法是双指针,所以没有用 upper_bound 和 lower_bound。
每次找较小值和较大值的部分时间复杂度是
代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
long long r[maxn], g[maxn], b[maxn];
long long ans;
long long calc(long long x, long long y, long long z)
{
return (x-y)*(x-y)+(y-z)*(y-z)+(x-z)*(x-z);
}
void solve(long long *x, long long *y, long long *z, int nx, int ny, int nz)
{
int p1 = 0, p2 = 0;
for(int i = 1; i <= nx; i++)
{
while(p1 <= ny && y[p1] <= x[i]) p1++; //找最接近的较小值
while(p2 <= nz && z[p2] < x[i]) p2++; //找最接近的较大值
if(p1 - 1 != 0 && p2 != nz + 1) //较小值和较大值都能找到
ans = min(ans, calc(x[i], y[p1 - 1], z[p2]));
}
return;
}
void work()
{
ans = 0x7fffffffffffffff; //CF的C++11的编译器不支持<limits.h>中的LONG_LONG_MAX
int nr, ng, nb;
scanf("%d%d%d", &nr, &ng, &nb);
for(int i = 1; i <= nr; i++) scanf("%lld", r + i);
for(int i = 1; i <= ng; i++) scanf("%lld", g + i);
for(int i = 1; i <= nb; i++) scanf("%lld", b + i);
sort(r + 1, r + nr + 1);
sort(g + 1, g + ng + 1);
sort(b + 1, b + nb + 1);
//枚举所有可能的大小关系
solve(r, g, b, nr, ng, nb);
solve(r, b, g, nr, nb, ng);
solve(g, r, b, ng, nr, nb);
solve(g, b, r, ng, nb, nr);
solve(b, r, g, nb, nr, ng);
solve(b, g, r, nb, ng, nr);
printf("%lld\n", ans);
return;
}
signed main()
{
int T;
scanf("%d", &T);
while(T--)
work();
return 0;
}