题目:
思路:
先将雪球按照体积升序排序,考虑二分答案,检查时枚举左侧雪球,分别计算右侧有多少雪球满足条件。
代码:
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
int n = 0;
int k = 0;
bool Check(long long int m,vector<long long int>a)//判断
{
long long int cnt = 0;
int i, j;
int t = n - 1;
for(i=0;i<n;i++)//枚举左侧雪球
{
for (j = t; j > i; j--)//判断右侧雪球
{
if (m > a[i] + a[j])
{
cnt += j - i;//统计个数
break;
}
}
t = j;
if (cnt >= k)return true;//个数大于k则为真
}
return false;
}
int main()
{
int t = 0; cin >> t;
while(t--)
{
cin >> n;
vector<long long int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];//输入各个雪球的大小
cin >> k;//输入寻找的雪球
sort(a.begin(), a.end());//升序排序
long long int l = a[0] + a[1];
long long int r = a[n - 1] + a[n - 2];
//二分查找答案
while (l < r)
{
long long int m = (l + r) / 2;
if (Check(m,a))r = m;//若是个数大于k则应该在m的左侧
else l = m + 1;//若是个数小于k则应该在m的右侧
}
if (l != a[n - 1] + a[n - 2])
cout << l - 1 << endl;//输出答案
else cout << l << endl;//输出答案
//system("pause");
//system("cls");
}
return 0;
}
对于输出时的if语句
这里二分查找答案若是查找的正好是n* (n - 1) / 2个小的雪球则在最后一个l=m+1赋值语句结束之后会退出循环,
例如1 2 7 8,找第六个小的雪球,
第一次 第二次 第三次 循环结束之前
l r m l r m l r m l r m
3 15 9 10 15 12 13 15 14 15 15 14(循环结束了)
若是1 2 7 8找第三个小的雪球
第一次 第二次 第三次 第四次 第五次 结束
l r m l r m l r m l r m l r m l r
3 15 9 10 15 12 10 12 11 10 11 10 10 10 10(应该结束) 10 10
则输出的时候不应该减一
测试用例:
1
4
2 3 4 5
3
输出 :7
样例中,可以合成 6 种不同的大雪球,按体积排序后为 [5,6,7,7,8,9],因此体积第 3 小的大雪球的体积为 7。