Description
这天,SJY显得无聊。在家自己玩。在一个棋盘上,有
Input
第一行两个数
以后
如果
如果
Output
对于每个
Sample Input
2 3
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
HINT
kdtree 可以过
题解
K-D Tree 膜板题
这里用的是替罪羊式加点,效率更高。
My Code
/**************************************************************
Problem: 2648
User: infinityedge
Language: C++
Result: Accepted
Time:17728 ms
Memory:48180 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define inf 0x3f3f3f3f
#define eps 1e-10
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
int Abs(int x){
return x > 0 ? x : -x;
}
struct point{
int x, y;
point(){}
point(int _x, int _y){
x = _x; y = _y;
}
}a[500005];
int cmpx(point a, point b){
return a.x < b.x;
}
int cmpy(point a, point b){
return a.y < b.y;
}
struct node{
int x, y, siz, dt;
int dx, dy, ux, uy;
int lc, rc, fa;
};
struct KDTree{
node d[1000005];
int sz, rt, lst, tot;
queue<int> q;
int newnode(){
if(!q.empty()){
int ret = q.front();
q.pop();
return lst = ret;
}
return lst = ++sz;
}
void pushup(int k){
d[k].dx = d[k].ux = d[k].x;
d[k].dy = d[k].uy = d[k].y;
d[k].siz = 1;
if(d[k].lc){
d[k].dx = min(d[k].dx, d[d[k].lc].dx);
d[k].dy = min(d[k].dy, d[d[k].lc].dy);
d[k].ux = max(d[k].ux, d[d[k].lc].ux);
d[k].uy = max(d[k].uy, d[d[k].lc].uy);
d[k].siz += d[d[k].lc].siz;
}
if(d[k].rc){
d[k].dx = min(d[k].dx, d[d[k].rc].dx);
d[k].dy = min(d[k].dy, d[d[k].rc].dy);
d[k].ux = max(d[k].ux, d[d[k].rc].ux);
d[k].uy = max(d[k].uy, d[d[k].rc].uy);
d[k].siz += d[d[k].lc].siz;
}
}
void build(int &k, int l, int r, int flag, int fa){
if(l > r) return;
k = newnode(); d[k].fa = fa; d[k].dt = flag;
// printf("%d %d %d\n", k, l, r);
if(l == r){
d[k].x = d[k].dx = d[k].ux = a[l].x; d[k].y = d[k].dy = d[k].uy = a[l].y;
return;
}
int mid = (l + r) >> 1;
if(flag) nth_element(a + l, a + mid, a + r, cmpx);
else nth_element(a + l, a + mid, a + r, cmpy);
d[k].x = a[mid].x; d[k].y = a[mid].y;
build(d[k].lc, l, mid - 1, flag ^ 1, k);
build(d[k].rc, mid + 1, r, flag ^ 1, k);
pushup(k);
}
int judge(int k){
if((d[d[k].lc].siz + 1) * 0.8 > d[k].siz + 1) return 1;
if((d[d[k].lc].siz + 1) * 0.8 > d[k].siz + 1) return 1;
return 0;
}
void dfs(int k){
q.push(k);
a[++tot] = point(d[k].x, d[k].y);
if(d[k].lc) dfs(d[k].lc);
if(d[k].rc) dfs(d[k].rc);
}
void rebuild(int k){
tot = 0;
if(k == rt){
dfs(k);
build(rt, 1, tot, 0, 0);
return;
}
int f = d[k].fa, wh = (d[f].rc == k);
dfs(k);
if(wh) build(d[f].rc, 1, tot, 0, d[f].dt ^ 1);
else build(d[f].lc, 1, tot, 0, d[f].dt ^ 1);
}
void ins(int k, int x, int y, int flag){
if(flag){
if(x <= d[k].x){
if(d[k].lc == 0){
a[1] = point(x, y);
build(d[k].lc, 1, 1, flag ^ 1, k);
}else ins(d[k].lc, x, y, flag ^ 1);
}else{
if(d[k].rc == 0){
a[1] = point(x, y);
build(d[k].rc, 1, 1, flag ^ 1, k);
}else ins(d[k].rc, x, y, flag ^ 1);
}
}else{
if(y <= d[k].y){
if(d[k].lc == 0){
a[1] = point(x, y);
build(d[k].lc, 1, 1, flag ^ 1, k);
}else ins(d[k].lc, x, y, flag ^ 1);
}else{
if(d[k].rc == 0){
a[1] = point(x, y);
build(d[k].rc, 1, 1, flag ^ 1, k);
}else ins(d[k].rc, x, y, flag ^ 1);
}
}
pushup(k);
}
void ins(int x, int y){
ins(rt, x, y, 0);
x = lst; int tmp = 0;
while(x != 0){
if(judge(x)) tmp = x;
x = d[x].fa;
}
if(tmp != 0){
rebuild(x);
}
}
int ans;
int get(int k, int x, int y){
int ret = 0;
ret += max(0, d[k].dx - x);
ret += max(0, d[k].dy - y);
ret += max(0, x - d[k].ux);
ret += max(0, y - d[k].uy);
return ret;
}
void query(int k, int x, int y){
// printf("%d %d %d\n", rt, d[k].x, d[k].y);
ans = min(ans, Abs(d[k].x - x) + Abs(d[k].y - y));
int dl = inf, dr = inf;
if(d[k].lc) dl = get(d[k].lc, x, y);
if(d[k].rc) dr = get(d[k].rc, x, y);
if(dl < dr){
if(dl < ans) query(d[k].lc, x, y);
if(dr < ans) query(d[k].rc, x, y);
}else{
if(dr < ans) query(d[k].rc, x, y);
if(dl < ans) query(d[k].lc, x, y);
}
}
int query(int x, int y){
ans = inf;
query(rt, x, y);
return ans;
}
}KDT;
int n, m;
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++){
int x, y;
scanf("%d%d", &x, &y);
a[i] = point(x, y);
}
KDT.build(KDT.rt, 1, n, 0, 0);
for(int i = 1; i <= m; i ++){
int opt, x, y;
scanf("%d%d%d", &opt, &x, &y);
if(opt == 1){
KDT.ins(x, y);
}else{
printf("%d\n", KDT.query(x, y));
}
}
return 0;
}