「CQOI2016」K 远点对

/*
考虑暴力  可以n ^ 2枚举点对 然后用一个容量为2k的小根堆来维护第k大
kd-tree呢就是来将这个暴力优化, 每次先找远的并且最远距离不如堆顶的话就不继续找下去
貌似挺难构造数据卡的
*/

#include<iostream>
#include<queue>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define M 100010
#define ll long long
#define inf 1000000000000000ll
#define sqr(x) 1ll * (x)* (x)
using namespace  std;
int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}
int n, k, q, root, lc[M], rc[M];
ll minn[M][2], maxx[M][2];
struct Note {
    ll d[2];
    bool operator < (const Note &b) const {
        return  d[q] != b.d[q] ? d[q] < b.d[q] : d[q^1] < b.d[q ^ 1];
    }
} tmp, ver[M];

priority_queue<ll, vector<ll>, greater<ll> >que;

void pushup(int x) {
    for(int i = 0; i <= 1; i++) {
        minn[x][i] = maxx[x][i] = ver[x].d[i];
        minn[x][i] = min(minn[x][i], min(minn[lc[x]][i], minn[rc[x]][i]));
        maxx[x][i] = max(maxx[x][i], max(maxx[lc[x]][i], maxx[rc[x]][i]));
    }
}

int build(int l, int r, int kx) {
    if(l > r) return 0;
    int mid = (l + r) >> 1;
    q = kx;
    nth_element(ver + l, ver + mid, ver + r + 1);
    lc[mid] = build(l, mid - 1, kx ^ 1);
    rc[mid] = build(mid + 1, r, kx ^ 1);
    pushup(mid);
    return mid;
}

ll get(int x) {
    if(!x) return 0;
    ll rt = 0;
    for(int i = 0; i <= 1; i++) rt += max(sqr(maxx[x][i] - tmp.d[i]), sqr(minn[x][i] - tmp.d[i]));
    return rt;
}

ll calc(Note a, Note b) {
    return sqr(a.d[0] - b.d[0]) + sqr(a.d[1]-b.d[1]);
}

void query(int x) {
    if(!x) return;
    ll dl = get(lc[x]), dr = get(rc[x]), d = calc(tmp, ver[x]);
    if(d > que.top()) que.pop(), que.push(d);
    if(dl > dr) {
        if(dl > que.top()) query(lc[x]);
        if(dr > que.top()) query(rc[x]);
    } else {
        if(dr > que.top()) query(rc[x]);
        if(dl > que.top()) query(lc[x]);
    }
}
int main() {
    n = read(), k = read();
    for(int i = 1; i <= n; i++) ver[i].d[0] = read(), ver[i].d[1] = read();
    for(int i = 0; i <= 1; i++) minn[0][i] = inf, maxx[0][i] = -inf;
    root = build(1, n, 0);
    for(int i = 1; i <= 2 * k; i++) que.push(0);
    for(int i = 1; i <= n; i++) tmp = ver[i],query(root);
    cout << que.top();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/luoyibujue/p/9247257.html