BZOJ 2648 SJY摆棋子

kd-tree

kd-tree不重构居然能过?23333。。。
就当屯一个模板吧。

#include<cstdio>
#include<algorithm>
#define N 1000005
#define cmin(u,v) (u)>(v)?(u)=(v):0
#define cmax(u,v) (u)<(v)?(u)=(v):0
using namespace std;
namespace ziqian
{
    int in()
    {
        int r = 0; char c = getchar();
        while(c<'0'||c>'9')c=getchar();
        while(c>='0'&&c<='9')r=r*10+c-'0',c=getchar();
        return r;
    }
    const int INF = 1<<30; 
    int D, root, ans, x, y; 
    struct Point{int d[2];}p[N];
    struct KDT{int d[2], x[2], y[2], ch[2];}t[N]; 
    bool operator < (Point a, Point b) {return a.d[D] < b.d[D] || (a.d[D] == b.d[D] && a.d[D^1] < b.d[D^1]);}
    void make_KDT(int f, int x)
    {
        cmin(t[f].x[0], t[x].x[0]); cmax(t[f].x[1], t[x].x[1]);
        cmin(t[f].y[0], t[x].y[0]); cmax(t[f].y[1], t[x].y[1]);
    }
    int build_KDT(int l, int r, int d)
    {
        D = d; int mid = (l+r)>>1;
        nth_element(p+l,p+mid,p+1+r);
        t[mid].d[0] = t[mid].x[0] = t[mid].x[1] = p[mid].d[0];
        t[mid].d[1] = t[mid].y[0] = t[mid].y[1] = p[mid].d[1];
        if(l<mid) t[mid].ch[0] = build_KDT(l,mid-1,d^1), make_KDT(mid,t[mid].ch[0]);else t[mid].ch[0] = 0;
        if(mid<r) t[mid].ch[1] = build_KDT(mid+1,r,d^1), make_KDT(mid,t[mid].ch[1]);else t[mid].ch[1] = 0;
        return mid;
    }
    void insert_KDT(int pos)
    {
        D = 0; 
        for(int o = root; o; D ^= 1)
        {
            make_KDT(o, pos);
            int &nxt = t[o].ch[ t[o].d[D] <= t[pos].d[D] ];
            if(!nxt){nxt = pos; return;} else o = nxt;
        }
    }
    int abs(int x){return x<0?-x:x;}
    int get_dis(int p){return max(t[p].x[0]-x,0)+max(x-t[p].x[1],0)+max(t[p].y[0]-y,0)+max(y-t[p].y[1],0);}
    void query_KDT(int o)
    {
        int tmp = abs(t[o].d[0]-x)+abs(t[o].d[1]-y), d[2] = {INF, INF}; cmin(ans, tmp);
        if(t[o].ch[0]) d[0] = get_dis(t[o].ch[0]); if(t[o].ch[1]) d[1] = get_dis(t[o].ch[1]);
        int nxt = d[1] <= d[0];
        if(d[nxt] < ans) query_KDT(t[o].ch[nxt]);
        if(d[nxt^1] < ans)query_KDT(t[o].ch[nxt^1]);
    }
    void main()
    {
        int n=in(), m=in();
        for(int i = 1; i <= n; i++)p[i].d[0] = in(), p[i].d[1]=in();
        root = build_KDT(1,n,0);
        for(int i = 1; i <= m; i++)
        {
            int opt = in();
            if(opt == 1)
            {
                ++n;
                t[n].d[0] = t[n].x[0] = t[n].x[1] = in();
                t[n].d[1] = t[n].y[0] = t[n].y[1] = in();
                insert_KDT(n);
            }
            else
            {
                x = in(); y = in(); ans = INF; query_KDT(root);
                printf("%d\n",ans);
            }
        }   
    }
}
int main()
{
    ziqian::main();
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值