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

BZOJ2716 【Violet III】天使玩偶

【Violet III】天使玩偶 K-D tree_第1张图片【Violet III】天使玩偶 K-D tree_第2张图片【Violet III】天使玩偶 K-D tree_第3张图片


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


#include
#include
#include
#define MAXN 1000005
#define Max(x,y) ((x>y)?(x):(y))
#define Min(x,y) ((x
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]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(l0]=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(lg0],x,y);
        if(rg1],x,y);
    }
    else
    {
        GetMin(T[p].son[1],x,y);
        if(lg0],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);
    }
}

你可能感兴趣的:(K-Dtree)