这天,SJY显得无聊。在家自己玩。在一个棋盘上,有 N 个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即 |x1−x2|+|y1−y2| 。现在给出 N≤500000 个初始棋子。和 M≤500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
Input
第一行两个数 N,M
以后 M 行,每行3个数 t x y
如果 t=1 那么放下一个黑色棋子
如果 t=2 那么放下一个白色棋子
Output
对于每个 t=2 输出一个最小距离
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
#include
#include
#include
#include
#include
#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;
}
评论
查看更多