题意:最近Xenia买了nr红色宝石,ng绿色宝石和nb蓝色宝石。每种宝石都有一个重量。假设所选宝石的重量为x、y和z,Xenia想找到(x-y)2+(y-z)2+(z-x)2的最小值。作为她亲爱的朋友,你能帮助她吗?
题解:
我们要找的钻石重量应该是符合这种规律的 a <= b<= c
那我们就假设现在的是b,二分寻找a与c
将三种宝石重量排序,r,g,b;
void getmin(vecl r, vecl g, vecl b) {
for (int i = 0; i < r.size(); i++) {
ll x1 = upper_bound(g.begin(), g.end(), r[i]) - g.begin();
ll x2 = lower_bound(b.begin(), b.end(), r[i]) - b.begin();
if (x1 == 0 || x2 == b.size()) continue;
x1--;
ll x = r[i], y = g[x1], z = b[x2];
Min = min(Min, pow2(x - y) + pow2(x - z) + pow2(y - z));
}
}
getmin(r, g, b);
getmin(r, b, g);
getmin(b, r, g);
getmin(b, g, r);
getmin(g, r, b);
getmin(g, b, r);
大部分人写的核心代码,遍历a很好理解,为什么一个是lower_bound,一个是upper_bound
因为a <= b<= c
要找的是一个在左边,一个在右边,upper_bound后下标又减一代表找的是左边,找右边好说
要换着再找一遍
并且三个都要考虑,所以是六遍
但是代码中这这一部分实在没搞明白
所以我自己写了下面的
if(x2 == c.size())
{
x2--;
}
if(x1 == b.size())
{
x1--;
}
else
{
if(x1!=0)
x1--;
}
首先判断越界情况,如果有要减,其次x1就是upper_bound找左边的情况,如果没有一个是大于当前的,返回的下标是0,就不能减了;
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define int long long
vector<int> r,g,b;
int mi = 9e18;
int pow2(int x)
{
return x*x;
}
void solve(vector<int>a,vector<int>b,vector<int>c)
{
for(int i = 0;i < a.size();i++)
{
int x1 = upper_bound(b.begin(),b.end(),a[i])-b.begin();
int x2 = lower_bound(c.begin(),c.end(),a[i])-c.begin();
if(x2 == c.size())
{
x2--;
}
if(x1 == b.size())
{
x1--;
}
else
{
if(x1!=0)
x1--;
}
mi = min(mi,pow2(a[i]-b[x1])+pow2(a[i]-c[x2])+pow2(b[x1]-c[x2]));
}
}
signed main()
{
int t;
cin >> t;
while(t--)
{
int nr,ng,nb;
cin >> nr >>ng >> nb;
r.clear();
g.clear();
b.clear();
for(int i = 1;i <= nr;i++)
{
int x;
cin >>x;
r.push_back(x);
}
for(int i = 1;i <= ng;i++)
{
int x;
cin >> x;
g.push_back(x);
}
for(int i = 1;i <= nb;i++)
{
int x;
cin >> x;
b.push_back(x);
}
mi = 9e18;
sort(r.begin(),r.end());
sort(g.begin(),g.end());
sort(b.begin(),b.end());
solve(r,g,b);
solve(r,b,g);
solve(g,r,b);
solve(g,b,r);
solve(b,r,g);
solve(b,g,r);
cout<<mi<<"\n";
}
}