【题意】\(n\) 个数的数组 \(a\),选择一个 \(x \in [0, 10^9]\) 使得 \(b_i = |a_i - x|\) 这个数组单调不减。
\(n \le 10^5, a_i \in [1, 10^8]\)
【分析】
看到题目,第一反应是拍到数轴上,选定点之后,向左单调递增,向右单调递增。然后根据两边谁会先进队来约束 \(x\)。但是这个东西会出很大问题,不在讨论范围。
这道题最好的做法是二分。考虑对于 \(mid\),如果存在 \(|a_i - x| > |a_{i + 1} - x|\),那么需要调整 \(mid\)。对于 \(a_i < a_{i + 1}\) 的情形,需要向左边调整,否则向右边调整。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
void cmax(int &x, int y) {if(x < y) x = y;}
void cmin(int &x, int y) {if(x > y) x = y;}
int a[200100];vector<pii> z;int n;
signed main() {
ios::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
//time_t start = clock();
//think twice,code once.
//think once,debug forever.
int T; cin >> T;
while(T--) {
z.clear();
cin>>n;
f(i, 1, n) {
cin >> a[i];
z.push_back({a[i],i});
}
sort(z.begin(), z.end());
int l = 0, r = inf; bool ok = 0;
while(l <= r) {
int mid = (l + r) >> 1;
int stt = 0;
f(i, 1, n - 1) {
if(abs(a[i] - mid) > abs(a[i + 1] - mid)) {
stt = (a[i] < a[i + 1] ? -1 : 1); //left, right
break;
}
}
if(stt == 0) {ok = 1; cout << mid << endl; break;}
else {
if(stt == -1) r = mid - 1;
else l = mid + 1;
}
}
if(!ok) cout << -1 << endl;
}
//time_t finish = clock();
//cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
return 0;
}
标签:10,int,cin,mid,stt,CF1772D,单调
From: https://www.cnblogs.com/Zeardoe/p/16994938.html