第 3 题:地标访问
#include <bits/stdc++.h>
using namespace std;
int n, t;
int x[50005], length[50005], num[2][50005], tot1, tot2;
bool check (int k) {
int res = 0x7fffffff;
for (int i = 1; i <= min(tot1, k); ++i) {//i表示负数坐标选取多少个
if (k - i > tot2) continue;//如果正数个数太多了,就没有后面的事情了
res = min(res, min(num[0][i], num[1][k - i]) * 2 + max(num[0][i], num[1][k - i]));//就是选取最小的重复走,大的走一遍,取和就行了
}
return res <= t;//如果没超时,就可以
}
int main() {
scanf("%d%d", &t, &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &x[i]);
}
sort(x + 1, x + 1 + n);//注意,这里必须要排序
for (int i = 1; i <= n; ++i) {
if (x[i] <= 0) num[0][++tot1] = (-x[i]);//负数分组
else num[1][++tot2] = x[i];//正数分组
}
for (int i = 1; i <= (tot1 + 1) / 2; ++i) {
swap(num[0][i], num[0][tot1 + 1 - i]);//注意,这里负数里面要从大到小来,这就是为什么要排序
}
int L = 0, R = n + 1;
while (L + 1 < R) {//二分
int mid = (L + R) >> 1;
if (check(mid)) L = mid;
else R = mid;
}
cout << L << endl;
return 0;
}