zoukankan      html  css  js  c++  java
  • BZOJ 2648: SJY摆棋子 kdtree

    2648: SJY摆棋子

    题目连接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2648

    Description

    这天,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

    Hint

    题意

    题解:

    kdtree裸题

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1000005;
    #define INF 1000000000
    struct arr{
        int d[2],min[2],max[2],l,r;
    };
    int D,root,x,y,ans,n,m,tot,op;;
    inline int cmp(arr a,arr b)
    {
        return a.d[D]<b.d[D]||a.d[D]==b.d[D]&&a.d[D^1]<b.d[D^1];
    }
    arr a[maxn];
    
    inline void up(int k,int s)
    {
        a[k].min[0]=min(a[k].min[0],a[s].min[0]);
        a[k].max[0]=max(a[k].max[0],a[s].max[0]);
        a[k].min[1]=min(a[k].min[1],a[s].min[1]);
        a[k].max[1]=max(a[k].max[1],a[s].max[1]);
    }
    int build(int l,int r,int dd)
    {
        D=dd;int mid=(l+r)>>1;
        nth_element(a+l+1,a+mid+1,a+r+1,cmp);
        a[mid].min[0]=a[mid].max[0]=a[mid].d[0];
        a[mid].min[1]=a[mid].max[1]=a[mid].d[1];
        if (l!=mid) a[mid].l=build(l,mid-1,dd^1);
        if (mid!=r) a[mid].r=build(mid+1,r,dd^1);
        if (a[mid].l) up(mid,a[mid].l);
        if (a[mid].r) up(mid,a[mid].r);
        return mid;
    }
    void insert(int k)
    {
        int p=root;D=0;
        while (1)
        {
            up(p,k);
            if (a[k].d[D]<=a[p].d[D]){if (!a[p].l) {a[p].l=k;return;} p=a[p].l;}
            else {if (!a[p].r) {a[p].r=k;return;} p=a[p].r;}
            D^=1;
        }
    }
    int getdis(int k)
    {
        int res=0;
        if (x<a[k].min[0]) res+=a[k].min[0]-x;
        if (x>a[k].max[0]) res+=x-a[k].max[0];
        if (y<a[k].min[1]) res+=a[k].min[1]-y;
        if (y>a[k].max[1]) res+=y-a[k].max[1];
        return res;
    }
    void ask(int k)
    {
      int d0=abs(a[k].d[0]-x)+abs(a[k].d[1]-y);
      if (d0<ans) ans=d0;
      int dl=(a[k].l)?getdis(a[k].l):INF;
      int dr=(a[k].r)?getdis(a[k].r):INF;
      if (dl<dr){if (dl<ans) ask(a[k].l);if (dr<ans) ask(a[k].r);}
      else {if (dr<ans) ask(a[k].r);if (dl<ans) ask(a[k].l);}
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i].d[0],&a[i].d[1]);
        }
        if(n)root = build(1,n,0);
        for(int i=1;i<=m;i++){
            scanf("%d",&op);
            if(op==1){
                n++;
                scanf("%d%d",&a[n].d[0],&a[n].d[1]);
                a[n].min[0]=a[n].max[0]=a[n].d[0];
                a[n].min[1]=a[n].max[1]=a[n].d[1];
                insert(n);
            }else if(op==2){
                ans=2000000000;
                scanf("%d%d",&x,&y);
                ask(root);
                printf("%d
    ",ans);
            }
        }
    }
  • 相关阅读:
    OpenEuler下OpenSSL的安装
    《Unix/Linux系统编程》第四章学习笔记
    缓冲区溢出实验
    2.3.1测试
    鲲鹏服务器测试
    第六章学习笔记(20191213兰毅达)
    第五章学习笔记(20191213兰毅达)
    stat命令的实现-mysate(20191213兰毅达)
    反汇编测试(20191213兰毅达)
    OpenEuler树莓派基础实验
  • 原文地址:https://www.cnblogs.com/qscqesze/p/6098972.html
Copyright © 2011-2022 走看看