bzoj2716 [Violet 3]天使玩偶(KDtree)

Description

Input

Output

Sample Input

100 100
81 23
27 16
52 58
44 24
25 95
34 2
96 25
8 14
97 50
97 18
64 3
47 22
55 28
89 37
75 45
67 22
90 8
65 45
68 93
87 8
61 45
69 72
38 57
58 76
45 34
88 54
27 8
35 34
70 81
25 24
97 97
4 43
39 38
82 68
27 58
2 21
92 88
96 70
97 29
14 53
6 42
1 2
35 84
64 88
63 57
53 40
82 59
49 56
75 72
29 30
50 1
40 83
52 94
22 35
39 1
94 88
89 96
79 46
33 75
31 42
33 95
6 83
90 66
37 54
35 64
17 66
48 37
30 8
95 51
3 51
90 33
29 48
94 78
53 7
1 26
73 35
18 33
99 78
83 59
23 87
4 17
53 91
98 3
54 82
85 92
77 8
56 74
4 5
63 1
26 8
42 15
48 98
27 11
70 98
36 9
78 92
34 40
42 82
64 83
75 47
2 51 55
1 7 62
2 21 62
1 36 39
1 35 89
1 84 15
2 19 24
1 58 53
2 52 34
1 98 49
1 4 100
1 17 25
1 30 56
1 69 43
2 57 23
2 23 13
1 98 25
2 50 27
1 84 63
2 84 81
2 84 77
1 60 23
2 15 27
1 9 51
1 31 11
1 96 56
2 20 85
1 46 32
1 60 88
2 92 48
1 68 5
2 90 17
1 16 46
2 67 5
2 29 83
1 84 70
2 68 27
1 99 33
2 39 89
2 38 28
1 42 3
1 10 60
2 56 29
2 12 60
2 46 51
2 15 73
1 93 42
1 78 82
1 66 20
1 46 17
2 48 5
1 59 61
1 87 59
2 98 72
1 49 3
2 21 10
1 15 4
1 48 14
2 67 75
2 83 77
1 88 65
2 100 93
2 58 83
1 29 80
2 31 88
2 92 94
1 96 66
1 61 82
2 87 24
1 64 83
1 28 87
2 72 90
2 7 3
1 86 3
2 26 53
2 71 2
2 88 24
1 69 60
1 92 44
2 74 94
1 12 78
2 1 2
1 4 73
1 58 5
1 62 14
2 64 58
2 39 45
1 99 27
1 42 21
1 87 2
2 16 98
2 17 21
2 41 20
1 46 72
1 11 62
2 68 29
1 64 66
2 90 42
2 63 35
1 64 71

Sample Output

3
8
6
7
7
6
6
12
11
4
5
6
8
1
7
6
4
9
2
2
8
9
6
4
7
5
8
7
5
5
5
7
7
5
6
6
8
6
0
2
7
12
4
2
8
3
10

HINT

Source

Vani原创 欢迎移步 OJ2648

[ Submit][ Status][ Discuss]



分析:
一眼KDtree裸题
详解请移步—>
这道题用KDtree是可以分分钟秒掉的,但是传说中还有一种CDQ分治解法
具体会在另一篇blog中讲解

这里写图片描述

tip

KDtree的是空间复杂度:N(实质上就是一种二叉树),注意这里要加上之后添加的结点
KDtree中的x,y一定是全局变量

dis函数要留心

#include
#include
#include
#include

using namespace std;

const int INF=0x33333333;
const int N=300010;
int root,n,m,x,y,opt,cmpd,ans;
struct node{
    int d[2],mn[2],mx[2],lc,rc;
};
node t[N<<1];

bool cmp(const node &a,const node &b)
{
    if (a.d[cmpd]!=b.d[cmpd]) return a.d[cmpd]else return a.d[!cmpd]int bh)     //维护当前结点所控制的区间大小 
{
    int lc=t[bh].lc;
    int rc=t[bh].rc;
    if (lc)
    {
        t[bh].mn[0]=min(t[bh].mn[0],t[lc].mn[0]);
        t[bh].mn[1]=min(t[bh].mn[1],t[lc].mn[1]);
        t[bh].mx[0]=max(t[bh].mx[0],t[lc].mx[0]);
        t[bh].mx[1]=max(t[bh].mx[1],t[lc].mx[1]);
    }
    if (rc)
    {
        t[bh].mn[0]=min(t[bh].mn[0],t[rc].mn[0]);
        t[bh].mn[1]=min(t[bh].mn[1],t[rc].mn[1]);
        t[bh].mx[0]=max(t[bh].mx[0],t[rc].mx[0]);
        t[bh].mx[1]=max(t[bh].mx[1],t[rc].mx[1]);
    } 
}

int build(int l,int r,int D)
{
    cmpd=D;
    int mid=(l+r)>>1;
    nth_element(t+l,t+mid+1,t+r+1,cmp);
    t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0];
    t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1];
    if (mid!=l) t[mid].lc=build(l,mid-1,!D);
    if (mid!=r) t[mid].rc=build(mid+1,r,!D);
    update(mid);
    return mid;       //不用忘了返回值 
}

void insert(int p)
{
    int D,now;
    D=0; now=root;
    while (1)
    {
        if (t[p].mn[0]0]) t[now].mn[0]=t[p].mn[0];   //按照插入结点修改维护范围 
        if (t[p].mn[1]1]) t[now].mn[1]=t[p].mn[1];
        if (t[p].mx[0]>t[now].mx[0]) t[now].mx[0]=t[p].mx[0];
        if (t[p].mx[1]>t[now].mx[1]) t[now].mx[1]=t[p].mx[1];
        if (t[p].d[D]>=t[now].d[D])
        {
            if (!t[now].rc)
            {
                t[now].rc=p;
                return;
            }
            else now=t[now].rc;
        }
        else
        {
            if (!t[now].lc)
            {
                t[now].lc=p;
                return;
            }
            else now=t[now].lc;
        }
        D=!D;
    }
}

int dis(int p,int x,int y)
{
    int d=0;
    if (x0]) d+=(t[p].mn[0]-x);
    if (x>t[p].mx[0]) d+=(x-t[p].mx[0]);
    if (y1]) d+=(t[p].mn[1]-y);
    if (y>t[p].mx[1]) d+=(y-t[p].mx[1]);
    return d;
}

void ask(int now)
{
    int dl,dr,d0;
    d0=abs(t[now].d[0]-x)+abs(t[now].d[1]-y);
    if (d00;

    if (t[now].lc) dl=dis(t[now].lc,x,y);
    else dl=INF;
    if (t[now].rc) dr=dis(t[now].rc,x,y);
    else dr=INF;

    if (dlif (dllc);     //距离近的先递归 
        if (drelse
    {
        if (drif (dllc);
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%d%d",&t[i].d[0],&t[i].d[1]);
    root=build(1,n,0);
    int opt;
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&opt,&x,&y);
        if (opt==1)
        {
            n++;
            t[n].d[0]=t[n].mn[0]=t[n].mx[0]=x;
            t[n].d[1]=t[n].mn[1]=t[n].mx[1]=y;
            insert(n);
        }
        else 
        {
            ans=INF;
            ask(root);
            printf("%d\n",ans);
        }
    }
    return 0;
}

你可能感兴趣的:(KDtree)