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

来源:互联网 发布:淘宝产品组合策略案例 编辑:程序博客网 时间:2024/05/01 18:06

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<cstdio>#include<iostream>#include<cstring>#include<algorithm>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]<b.d[cmpd];    else return a.d[!cmpd]<b.d[!cmpd];}void update(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]<t[now].mn[0]) t[now].mn[0]=t[p].mn[0];   //按照插入结点修改维护范围         if (t[p].mn[1]<t[now].mn[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 (x<t[p].mn[0]) d+=(t[p].mn[0]-x);    if (x>t[p].mx[0]) d+=(x-t[p].mx[0]);    if (y<t[p].mn[1]) 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 (d0<ans) ans=d0;    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 (dl<dr)    {        if (dl<ans) ask(t[now].lc);     //距离近的先递归         if (dr<ans) ask(t[now].rc);    }    else    {        if (dr<ans) ask(t[now].rc);        if (dl<ans) ask(t[now].lc);    }}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;}
阅读全文
0 0