CF1772D

【题意】\(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;
}
posted @ 2022-12-20 19:28  OIer某罗  阅读(27)  评论(0编辑  收藏  举报