CF1904C Array Game

题目传送门

codeforces

洛谷

题目大意

给你一个由 n 个正整数组成的数组 a 。在一次操作中,选取 (i,j) ,将 |aiaj| 加到 a 的末尾。你的任务是在执行 k 操作后,最小化最后数组 a 的最小值。

思路

分三种情况:

  • k3 时,我们可以取两次相同的 |aiaj| ,这样数组中就会出现两个相同的数,第三次操作取这两个相同的数即可,可以保证最小值为 0

  • k=1 时,我们暴力枚举每组 |aiaj| ,然后直接取数组 a 和枚举出的每组 |aiaj| 的最小值;

  • k=2 时,我们考虑先暴力枚举出每组 |aiaj| ,并对原数组 a 排序,对于每个得到的 |aiaj| ,在排好序的原数组 a 中二分找到与这个值最接近的数,和它取差值,最后答案就是原数组 a 、暴力枚举出每个 |aiaj| 、二分找到的数取的差值,这三组数中的最小值。

最坏情况时间复杂度 O(n2logn) ,可以接受。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
void solve()
{
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
if (k >= 3)
{
cout << 0 << endl;
return;
}
int minn = LLONG_MAX;
for (int i = 0; i < n; i++)
{
minn = min(minn, a[i]);
}
vector<int> b;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
int c = abs(a[i] - a[j]);
b.push_back(c);
minn = min(minn, c);
}
}
if (k == 1)
{
cout << minn << endl;
return;
}
sort(a.begin(), a.end());
for (auto i : b)
{
int l = 0, r = n - 1, mid, d = 0;
while (l <= r)
{
mid = (l + r) >> 1;
if (a[mid] <= i)
{
l = mid + 1;
d = mid;
}
else
{
r = mid - 1;
}
}
minn = min(minn, abs(a[d] - i));
if (d != n - 1)
minn = min(minn, abs(a[d + 1] - i));
}
cout << minn << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
solve();
}
}
posted @   Zinc_Acetate  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示