信息
- ID
- 1217
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 33
- 已通过
- 5
- 上传者
如果k>=3 答案一定为0
证明如下: 任选两个数x,y (y >= x),进行一次操作,得到|x-y|,再将|x-y| 和y进行一次操作,得到|x|,然后|x|和x进行操作,答案为0.
然后当k = 1时,我们容易想到将数组排序,然后找最小的相邻差值,然后和最小数a[1]进行比较。
当k==2,我们考虑ans存在的情况,
(1):进行第一次操作,找最小的相邻最小值,然后和a[1]比较进行第二次操作,更新最大ans
(2):还有一种可能答案可能并不在相邻数中去最值,比如
数组a[]:1 4 6 10
差值:3 2 4
最优解应该是 |10-4| = 6, |6-6| = 0;
n的范围可以让我们以O(n^2)的时间复杂度去模拟,我们可以找出来每两个数之间的差值
然后排序,对于a[i],每次用log的时间复杂度去在差值数组中查找最近的c_i,然后更新ans
最后ans取这两种情况最小的即可
#define rep(i,l,r) for(int i = l; i <= r; i++)
#define int long long
#define pb push_back
#define endl '\n'
using namespace std;
const int inf = 1e18+5;
void solve() {
int n,k; cin >> n >> k;
vector<int> a(n+1);
rep(i,1,n) cin >> a[i];
if(k >= 3){
cout << 0 << endl;
return;
}
sort(a.begin() + 1,a.end());
if(k == 1){
int mn = a[1];
rep(i,2,n) mn = min(mn,a[i] - a[i-1]);
cout << mn << endl;
}else{
int mn = inf;
rep(i,2,n) mn = min(mn,a[i] - a[i-1]);
int ans = min(abs(mn - a[1]),min(mn,a[1]));
vector<int> c;
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
c.pb(abs(a[i]- a[j]));
}
}
sort(c.begin(),c.end());
int len = c.size();
for(int i = 1; i <= n; i++){
int l = 0,r = len - 1;
while(l < r){
int mid = (l + r) / 2;
if(c[mid] >= a[i]){
r = mid;
}else{
l = mid + 1;
}
}
ans = min(ans,abs(c[l] - a[i]));
l = 0,r = len - 1;
while(l < r){
int mid = (l + r + 1) / 2;
if(c[mid] <= a[i]){
l = mid;
}else{
r = mid - 1;
}
}
ans = min(ans,abs(a[i] - c[l]));
}
cout << ans << endl;
}
}
考察 贪心,模拟,时间复杂度的判断。
首先最重要的是判断k的情况,不然很难做。
然后特判k=1,和k=2。
分情况讨论即可。