[Gym-101482] G-Gathering (three points set of three points + prefix sum)

Title

The 2-dimensional plane gives n integral points, find an integral point (x, y) so that the Manhattan distance from this integral point to the other n points is the smallest, and it needs to meet the Manhattan distance from each point to this (x, y) Not more than d.
n ≤ 1 e 5, 0 ≤ xi, yi ≤ 1 e 9, 0 ≤ d ≤ 2 e 9 n\le 1e5, 0 \le x_i, y_i \le 1e9, 0 \le d \le 2e9n1e5,0xi,andi1e9,0d2 e 9

Problem solving ideas

If there is no limit of "the Manhattan distance from each point to this (x, y) does not exceed d.", then easy access (median of x, median of y) is the best point.
Considering the restriction, we find that every Each point has a diamond-shaped optional area. The intersection of the n diamond-shaped optional areas is the area we can choose. This area can actually be seen as an area framed by 4 straight lines, then we maintain these 4 straight lines The legal area can be obtained.
Note that when x is determined, the function of the answer with respect to y is a concave function. Similarly, when x changes, y is used as the optimal selection position for each x, then the answer is a function of x It is also a concave function, so the three-point set of three-points is done.
When looking for the answer, you can use the two-point + prefix sum to quickly get the sum of the Manhattan distances from n points to the specified point.

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define fors(i, a, b) for(int i = (a); i < (b); ++i)
#define P pair<int,int>
using namespace std;
const int maxn = 1e5 + 50;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n;
ll xsum[maxn], ysum[maxn];
ll x[maxn], y[maxn];
ll d;
ll L = -inf, R = inf;//x-y
ll D = -inf, U = inf;//x+y
ll f(ll a, ll b[], ll c[]){
    
    
    if(a > b[n]){
    
    
        return (ll)n*a - c[n];
    }else if(a < b[0]){
    
    
        return c[n]-n*a;
    }else{
    
    
        int p = lower_bound(b+1, b+1+n, a)-b;
        return (c[n] - c[p-1] - (ll)(n-p+1)*a) + (ll)(p-1)*a - c[p-1];
    }
}
bool in(int x, int y){
    
    
    ll t1 = x-y;
    ll t2 = x+y;
    //cout<<"L:"<<L<<" R:"<<R<<" D:"<<D<<" U:"<<U<<endl;
    return L<=t1 && t1 <= R && D <= t2 && t2 <= U;
}
ll sol(ll a){
    
    
    ll l = max(a-R, D-a);
    ll r = min(a-L, U-a);
    if(r < l) return inf;
    ll ans = inf;
    while(r-l >= 3){
    
    
        ll lmid = l + (r-l)/3;
        ll rmid = r - (r-l)/3;
        ll la = f(lmid, y, ysum), ra = f(rmid, y, ysum);
        if(la >= ra) ans = min(ra, ans), l = lmid;
        else ans = min(ans, la), r = rmid;
    }
    while(l <= r) ans = min(ans, f(l, y, ysum)), l++;
    return ans;
}
int main()
{
    
    
    scanf("%d", &n);
    fors(i, 1, n+1) {
    
    
        scanf("%lld%lld", &x[i], &y[i]);
    }
    cin>>d;
    fors(i, 1, n+1){
    
    
        L = max(L, x[i] - y[i]-d);
        R = min(R, x[i] - y[i]+d);
        D = max(D, x[i] + y[i]-d);
        U = min(U, x[i] + y[i]+d);
    }
    sort(x+1, x+1+n); sort(y+1, y+1+n);
    fors(i, 1, n+1) xsum[i] = xsum[i-1] + x[i], ysum[i] = ysum[i-1] + y[i];
    if(in(x[n/2], y[n/2])){
    
    
        cout<<f(x[(n+1)/2], x, xsum)+f(y[(n+1)/2], y, ysum)<<endl;
    }else if(U < D || R < L){
    
    
        printf("impossible\n");
    }else {
    
    
        ll ans = inf;
        ll l = (D+L+1)/2;
        ll r = (R+U)/2;
        //cout<<"l:"<<l<<" r:"<<r<<endl;
        while(r-l >= 3){
    
    
            ll lmid = l + (r-l)/3;
            ll rmid = r - (r-l)/3;
            ll la = sol(lmid) + f(lmid, x, xsum);
            ll ra = sol(rmid) + f(rmid, x, xsum);
            if(la >= ra) ans = min(ans, ra), l = lmid;
            else ans = min(ans, la), r = rmid;
        }
        while(l <= r) ans = min(ans, sol(l)+f(l, x, xsum)), l++;
        cout<<ans<<endl;
    }
}
/*
5
3 1
4 1
5 9
2 6
5 3
4

*/

Guess you like

Origin blog.csdn.net/qq_43202683/article/details/105631998