BZOJ 2648 SJY摆棋子

Posted on 2016-03-31 19:03  ziliuziliu  阅读(163)  评论(0编辑  收藏  举报

kd树模板。这玩意儿我现在理解的还不是很透彻因此暂时没有更多的解释。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 505000
#define inf 1000000007
using namespace std;
struct kd
{
    int mx[3],mi[3],d[3];
    int l,r;
}t[maxn<<1];
struct point
{
    int num[3];
}p[maxn],regis;
int n,m,type,x,y,root,D,ans;
bool cmp(point a,point b)
{
    return a.num[D]<b.num[D];
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void update(int k)
{
    int ls=t[k].l,rs=t[k].r;
    for (int i=0;i<=1;i++)
    {
        if (ls) t[k].mx[i]=max(t[k].mx[i],t[ls].mx[i]);
        if (ls) t[k].mi[i]=min(t[k].mi[i],t[ls].mi[i]);
        if (rs) t[k].mx[i]=max(t[k].mx[i],t[rs].mx[i]);
        if (rs) t[k].mi[i]=min(t[k].mi[i],t[rs].mi[i]);
    }
}
int build(int left,int right,int split)
{
    D=split;int mid=(left+right)>>1;
    nth_element(p+left,p+mid,p+right+1,cmp);
    for (int i=0;i<=1;i++)
    {
        t[mid].mx[i]=p[mid].num[i];
        t[mid].mi[i]=t[mid].mx[i];
        t[mid].d[i]=t[mid].mi[i];
    }
    if (left<mid) t[mid].l=build(left,mid-1,split^1);
    if (mid<right) t[mid].r=build(mid+1,right,split^1);
    update(mid);
    return mid;
}
void insert(int now,int split)
{
    if (regis.num[split]>=t[now].d[split])
    {
        if (t[now].r) insert(t[now].r,split^1);
        else
        {
            t[now].r=++n;
            for (int i=0;i<=1;i++)
            {
                t[n].mx[i]=regis.num[i];
                t[n].mi[i]=regis.num[i];
                t[n].d[i]=regis.num[i];
            }
        }
    }
    else
    {
        if (t[now].l) insert(t[now].l,split^1);
        else
        {
            t[now].l=++n;
            for (int i=0;i<=1;i++)
            {
                t[n].mx[i]=regis.num[i];
                t[n].mi[i]=regis.num[i];
                t[n].d[i]=regis.num[i];
            }
        }
    }
    update(now);
}
int getdis(int k)
{
    int tmp=0;
    for(int i=0;i<2;i++)
        tmp+=max(0,t[k].mi[i]-regis.num[i]);
    for(int i=0;i<2;i++)
        tmp+=max(0,regis.num[i]-t[k].mx[i]);
    return tmp;
}
void ask(int now,int split)
{
    int d0,dl,dr;
    d0=abs(t[now].d[0]-regis.num[0])+abs(t[now].d[1]-regis.num[1]);
    ans=min(ans,d0);
    if (t[now].l) dl=getdis(t[now].l);else dl=inf;
    if (t[now].r) dr=getdis(t[now].r);else dr=inf;
    if (dl<dr)
    {
        if (dl<ans) ask(t[now].l,split^1);
        if (dr<ans) ask(t[now].r,split^1);
    }
    else
    {
        if (dr<ans) ask(t[now].r,split^1);
        if (dl<ans) ask(t[now].l,split^1);
    }
}
int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++)
    {
        x=read();y=read();
        p[i].num[0]=x;p[i].num[1]=y;
    }
    root=build(1,n,0);
    for (int i=1;i<=m;i++)
    {
        type=read();x=read();y=read();
        regis.num[0]=x;regis.num[1]=y;
        if (type==1) insert(root,0);
        else
        {
            ans=inf;
            ask(root,0);
            printf("%d\n",ans);
        }
    }
    return 0;
}