bzoj 2648 (kdtree模板题)

来源:互联网 发布:最准彩票预测软件 编辑:程序博客网 时间:2024/06/07 14:27
这天,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

转:http://www.cnblogs.com/ljh2000-jump/p/5513620.html


#include <bits/stdc++.h>using namespace std; const int MAXN = 1000011;const int inf=(1<<30);int n,m;int nowD;int root;int ans;int ql,qr; struct node{    int Min[2],Max[2];    int d[2];    int l,r;}t[MAXN*2]; inline int getint(){    int w=0,q=0;    char c=getchar();    while((c<'0'||c>'9')&&c!='-') c=getchar();    if(c=='-') q=1,c=getchar();    while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();    return q?-w:w;} inline int dist(int p){    int dis=0;    if(ql<t[p].Min[0]) dis+=t[p].Min[0]-ql;    if(ql>t[p].Max[0]) dis+=ql-t[p].Max[0];    if(qr<t[p].Min[1]) dis+=t[p].Min[1]-qr;    if(qr>t[p].Max[1]) dis+=qr-t[p].Max[1];    return dis;} inline bool cmp(node q,node qq){    if(q.d[nowD]==qq.d[nowD]) return q.d[!nowD]<qq.d[!nowD];    return q.d[nowD]<qq.d[nowD];} inline void kd_updata(int now){    if(t[now].l)    {        if(t[t[now].l].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].l].Max[0];        if(t[t[now].l].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].l].Max[1];        if(t[t[now].l].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].l].Min[0];        if(t[t[now].l].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].l].Min[1];    }    if(t[now].r)    {        if(t[t[now].r].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].r].Max[0];        if(t[t[now].r].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].r].Max[1];        if(t[t[now].r].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].r].Min[0];        if(t[t[now].r].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].r].Min[1];    }} inline int kd_build(int l,int r,int D){    int mid=(l+r)/2;    nowD=D;    nth_element(t+l+1,t+mid+1,t+r+1,cmp);     if(l!=mid) t[mid].l=kd_build(l,mid-1,!D);    if(r!=mid) t[mid].r=kd_build(mid+1,r,!D);    t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];    t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];    kd_updata(mid);    return mid;} inline void kd_insert(int now){    int p=root,D=0;    while(1)    {        if(t[now].Max[0]>t[p].Max[0]) t[p].Max[0]=t[now].Max[0];        if(t[now].Max[1]>t[p].Max[1]) t[p].Max[1]=t[now].Max[1];        if(t[now].Min[0]<t[p].Min[0]) t[p].Min[0]=t[now].Min[0];        if(t[now].Min[1]<t[p].Min[1]) t[p].Min[1]=t[now].Min[1];         if(t[now].d[D]>=t[p].d[D])        {            if(!t[p].r)            {                t[p].r=now;                return ;            }            else p=t[p].r;        }        else        {            if(!t[p].l)            {                t[p].l=now;                return ;            }            else p=t[p].l;        }        D=!D;    }} inline void kd_query(int p){    int dl,dr,d0;    d0=abs(t[p].d[0]-ql)+abs(t[p].d[1]-qr);    if(d0<ans) ans=d0;    if(t[p].l) dl=dist(t[p].l);else dl=inf;    if(t[p].r) dr=dist(t[p].r);else dr=inf;     if(dl<dr)    {        if(dl<ans) kd_query(t[p].l);        if(dr<ans) kd_query(t[p].r);    }    else    {        if(dr<ans) kd_query(t[p].r);        if(dl<ans) kd_query(t[p].l);    }}int main(){    n=getint();    m=getint();    for(int i=1;i<=n;i++) t[i].d[0]=getint(),t[i].d[1]=getint();        root=kd_build(1,n,0);    int x,y,z;    for(int i=1;i<=m;i++)    {        x=getint(),y=getint(),z=getint();        if(x==1)        {            n++;            t[n].Max[0]=t[n].Min[0]=t[n].d[0]=y;            t[n].Max[1]=t[n].Min[1]=t[n].d[1]=z;            kd_insert(n);        }        else        {            ans=inf;            ql=y,qr=z;            kd_query(root);            printf("%d\n",ans );        }    }}