【Violet III】天使玩偶 K-D tree

来源:互联网 发布:php location延时跳转 编辑:程序博客网 时间:2024/05/01 09:17

BZOJ2716 【Violet III】天使玩偶

这里写图片描述这里写图片描述这里写图片描述


K-D tree裸题。对于插入操作可以离线处理,即先把原始的点和所有的即将插入的点一开始全部放在K-D tree里,把一开始没有的点打上标记。在更新答案时,如果没有标记才进行更新。那么添加操作就是单点查找,取消标记。不需要考虑是否有坐标相同的点,因为关注的仅仅是点的坐标。


#include<stdio.h>#include<algorithm>#include<cmath>#define MAXN 1000005#define Max(x,y) ((x>y)?(x):(y))#define Min(x,y) ((x<y)?(x):(y))using namespace std;int N,M;int D;struct node{    int d[2],x[2],y[2],son[2];    bool mark;    bool operator<(const node &x)const{return d[D]<x.d[D];}}T[MAXN],A[MAXN];struct Input{int op,x,y;}qry[MAXN];void Update(int p,int s){    T[p].x[0]=Min(T[p].x[0],T[s].x[0]);    T[p].x[1]=Max(T[p].x[1],T[s].x[1]);    T[p].y[0]=Min(T[p].y[0],T[s].y[0]);    T[p].y[1]=Max(T[p].y[1],T[s].y[1]);}int rt,tot;int Build(int l,int r,int d){    D=d;    int p=++tot,mid=l+r>>1;    nth_element(A+l,A+mid,A+r+1);    T[p].d[0]=T[p].x[0]=T[p].x[1]=A[mid].d[0];    T[p].d[1]=T[p].y[0]=T[p].y[1]=A[mid].d[1];    T[p].mark=A[mid].mark;    if(l<mid)T[p].son[0]=Build(l,mid-1,d^1),Update(p,T[p].son[0]);    if(r>mid)T[p].son[1]=Build(mid+1,r,d^1),Update(p,T[p].son[1]);    return p;}int G(int p,int x,int y){    int dx,dy;    dx=Max(0,(T[p].x[0]-x))+Max(0,(x-T[p].x[1]));    dy=Max(0,(T[p].y[0]-y))+Max(0,(y-T[p].y[1]));    return dx+dy;}int MinDis;void GetMin(int p,int x,int y){    if(!T[p].mark)MinDis=Min(MinDis,(abs(x-T[p].d[0])+abs(y-T[p].d[1])));    int lg=1e9,rg=1e9;    if(T[p].son[0])lg=G(T[p].son[0],x,y);    if(T[p].son[1])rg=G(T[p].son[1],x,y);    if(lg>=MinDis&&rg>=MinDis)return;    if(lg<rg)    {        GetMin(T[p].son[0],x,y);        if(rg<MinDis)GetMin(T[p].son[1],x,y);    }    else    {        GetMin(T[p].son[1],x,y);        if(lg<MinDis)GetMin(T[p].son[0],x,y);    }}void Del(int p,int x,int y,int d)//删除标记{    if(T[p].d[0]==x&&T[p].d[1]==y){T[p].mark=false;return;}    int ls=T[p].son[0],rs=T[p].son[1];    if(!d)    {        if(ls&&T[ls].x[0]<=x&&T[ls].x[1]>=x)Del(ls,x,y,d^1);        if(rs&&T[rs].x[0]<=x&&T[rs].x[1]>=x)Del(rs,x,y,d^1);    }    else    {        if(ls&&T[ls].y[0]<=y&&T[ls].y[1]>=y)Del(ls,x,y,d^1);        if(rs&&T[rs].y[0]<=y&&T[rs].y[1]>=y)Del(rs,x,y,d^1);    }}int main(){    int i,cnt=0;    scanf("%d%d",&N,&M);    for(i=1;i<=N;i++)cnt++,scanf("%d%d",&A[cnt].d[0],&A[cnt].d[1]);    for(i=1;i<=M;i++)    {        scanf("%d%d%d",&qry[i].op,&qry[i].x,&qry[i].y);        if(qry[i].op==1)        {            cnt++;            A[cnt].d[0]=qry[i].x;A[cnt].d[1]=qry[i].y;A[cnt].mark=true;        }    }    rt=Build(1,cnt,0);    for(i=1;i<=M;i++)    {        if(qry[i].op==1)Del(rt,qry[i].x,qry[i].y,0);        else MinDis=1e9,GetMin(rt,qry[i].x,qry[i].y),printf("%d\n",MinDis);    }}
原创粉丝点击