【LG4169】[Violet]天使玩偶/SJY摆棋子

【LG4169】[Violet]天使玩偶/SJY摆棋子

题面

洛谷

题解

至于\(cdq\)分治的解法,以前写过
\(kdTree\)的解法好像还\(sb\)一些
就是记一下子树的横、纵坐标最值然后求一下点到矩形得到距离
之后再剪枝即可
为什么不吸氧还是跑不过啊

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm> 
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
}
void chkmin(int &x, int y) { if (x > y) x = y; } 
void chkmax(int &x, int y) { if (x < y) x = y; } 
const int MAX_N = 1e6 + 5;
const double alpha = 0.75;
const int INF = 1e9; 
struct Point { int x[2]; } p[MAX_N]; 
struct Node {
    int mn[2], mx[2], ls, rs, size;
    Point tp; 
} t[MAX_N]; 
int N, M, rt, cur, top, WD, ans, rub[MAX_N];
bool operator < (const Point &l, const Point &r) { return l.x[WD] < r.x[WD]; }
int newnode() {
    if (top) return rub[top--]; 
    else return ++cur; 
}
void pushup(int o) {
    int ls = t[o].ls, rs = t[o].rs; 
    for (int i = 0; i <= 1; i++) {
        t[o].mn[i] = t[o].mx[i] = t[o].tp.x[i]; 
        if (ls) chkmin(t[o].mn[i], t[ls].mn[i]), chkmax(t[o].mx[i], t[ls].mx[i]); 
        if (rs) chkmin(t[o].mn[i], t[rs].mn[i]), chkmax(t[o].mx[i], t[rs].mx[i]); 
    }
    t[o].size = t[ls].size + t[rs].size + 1; 
} 
int build(int l, int r, int wd) {
    if (l > r) return 0; 
    int o = newnode(), mid = (l + r) >> 1; 
    WD = wd, nth_element(&p[l], &p[mid], &p[r + 1]), t[o].tp = p[mid]; 
    t[o].ls = build(l, mid - 1, wd ^ 1), t[o].rs = build(mid + 1, r, wd ^ 1);
    return pushup(o), o; 
}
void pia(int o, int num) { 
    if (t[o].ls) pia(t[o].ls, num);
    p[num + t[t[o].ls].size + 1] = t[o].tp, rub[++top] = o; 
    if (t[o].rs) pia(t[o].rs, num + t[t[o].ls].size + 1); 
} 
void check(int &o, int wd) {
    if (alpha * t[o].size < t[t[o].ls].size || alpha * t[o].size < t[t[o].rs].size) 
        pia(o, 0), o = build(1, t[o].size, wd); 
}
void insert(int &o, int wd, Point tmp) {
    if (!o) return (void)(o = newnode(), t[o].tp = tmp, t[o].ls = t[o].rs = 0, pushup(o));
    if (t[o].tp.x[wd] < tmp.x[wd]) insert(t[o].r
91s, wd ^ 1, tmp); 
    else insert(t[o].ls, wd ^ 1, tmp); 
    pushup(o), check(o, wd); 
}
int getdis(int o, Point tmp) { 
    int res = 0;
    for (int i = 0; i <= 1; i++) res += max(0, tmp.x[i] - t[o].mx[i]) + max(0, t[o].mn[i] - tmp.x[i]);
    return res; 
}
int dist(Point a, Point b) { return abs(a.x[0] - b.x[0]) + abs(a.x[1] - b.x[1]); }
void query(int o, Point tmp) { 
    ans = min(ans, dist(tmp, t[o].tp)); 
    int dl = INF, dr = INF; 
    if (t[o].ls) dl = getdis(t[o].ls, tmp); 
    if (t[o].rs) dr = getdis(t[o].rs, tmp);
    if (dl < dr) {
        if (dl < ans) query(t[o].ls, tmp); 
        if (dr < ans) query(t[o].rs, tmp); 
    } else {
        if (dr < ans) query(t[o].rs, tmp);
        if (dl < ans) query(t[o].ls, tmp); 
    } 
}

int main () {
    N = gi(), M = gi(); 
    for (int i = 1; i <= N; i++) p[i].x[0] = gi(), p[i].x[1] = gi();
    rt = build(1, N, 0);
    while (M--) {
        Point tmp;
        int op = gi(); tmp.x[0] = gi(), tmp.x[1] = gi();
        if (op == 1) insert(rt, 0, tmp);
        else ans = INF, query(rt, tmp), printf("%d\n", ans); 
    } 
    return 0; 
} 
posted @ 2018-12-30 16:24  heyujun  阅读(243)  评论(0编辑  收藏  举报