【BZOJ-2648&2716】SJY摆棋子&天使玩偶 KD Tree

2648: SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 2459  Solved: 834
[Submit][Status][Discuss]

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可以过

Source

鸣谢 孙嘉裕

2716: [Violet 3]天使玩偶

Time Limit: 80 Sec  Memory Limit: 128 MB
Submit: 1098  Solved: 485
[Submit][Status][Discuss]

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 Input

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
Sample Output

HINT

 

Source

Vani原创 欢迎移步 OJ2648

Solution

双倍经验题,KD Tree模板题

KD Tree是一种切割多维空间的数据结构,主要用于多维空间信息的搜索(范围搜索和最近邻搜索)

大体上每层按照不同的维度进行左右建树,分开平面上的点,本质还是一颗平衡二叉树

效率大概是$O(log^{2}N)$的,比较暴力的做法

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
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;
}
#define maxn 500010
int n,m,D;
struct PointNode
{
    int d[2],mn[2],mx[2],l,r;
    PointNode(int x=0,int y=0) {l=r=0;d[0]=x;d[1]=y;}
    bool operator < (const PointNode & A) const {return d[D]<A.d[D];}
}p[maxn];
int dis(PointNode a,PointNode b) {return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);}
struct K_DTreeNode
{
    int rt,ans;
    PointNode Point,tree[maxn<<1];
    void Update(int now)
        {
            for (int i=0; i<=1; i++)
                {
                    if (tree[now].l) 
                        tree[now].mn[i]=min(tree[now].mn[i],tree[tree[now].l].mn[i]),tree[now].mx[i]=max(tree[now].mx[i],tree[tree[now].l].mx[i]);
                    if (tree[now].r) 
                        tree[now].mn[i]=min(tree[now].mn[i],tree[tree[now].r].mn[i]),tree[now].mx[i]=max(tree[now].mx[i],tree[tree[now].r].mx[i]);
                }
        }
    int BuildTree(int l,int r,int dd)
        {
            D=dd; int mid=(l+r)>>1;
            nth_element(p+l,p+mid,p+r+1);
            tree[mid]=p[mid];
            for (int i=0; i<=1; i++) tree[mid].mn[i]=tree[mid].mx[i]=tree[mid].d[i];
            if (l<mid) tree[mid].l=BuildTree(l,mid-1,dd^1);
            if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1);
            Update(mid);
            return mid;
        }
    void Insert(int now,int dd)
        {        
            if (Point.d[dd]>=tree[now].d[dd])
                if (tree[now].r) Insert(tree[now].r,dd^1);
                else
                    {
                        tree[now].r=++n; tree[n]=Point;
                        for (int i=0; i<=1; i++) tree[n].mn[i]=tree[n].mx[i]=tree[n].d[i];                
                    }
            else
                if (tree[now].l) Insert(tree[now].l,dd^1);
                else
                    {
                        tree[now].l=++n; tree[n]=Point;
                        for (int i=0; i<=1; i++) tree[n].mn[i]=tree[n].mx[i]=tree[n].d[i];                
                    }
            Update(now);            
        }
    int dist(int p1,PointNode p)
        {
               int re=0;
               for (int i=0; i<=1; i++) re+=max(0,tree[p1].mn[i]-p.d[i]);
               for (int i=0; i<=1; i++) re+=max(0,p.d[i]-tree[p1].mx[i]);
               return re;
        }
    void Query(int now,int dd)
        {
               int dl,dr,d0;
               d0=dis(tree[now],Point);
               if (d0<ans) ans=d0;
               if (tree[now].l) dl=dist(tree[now].l,Point); else dl=0x7f7f7f7f;
               if (tree[now].r) dr=dist(tree[now].r,Point); else dr=0x7f7f7f7f;
               if (dl<dr)
                {
                       if (dl<ans) Query(tree[now].l,dd^1);
                       if (dr<ans) Query(tree[now].r,dd^1);
                   }
            else
                {
                       if (dr<ans) Query(tree[now].r,dd^1);
                       if (dl<ans) Query(tree[now].l,dd^1);
                   }        
    }
    void insert(PointNode _p){Point=_p; Insert(rt,0);}
    void init(){rt=BuildTree(1,n,0);}
    int query(PointNode _p){Point=_p;ans=0x7fffffff; Query(rt,0); return ans;}
}KDT;
int main()
{
//    freopen("angel.in","r",stdin); freopen("angel.out","w",stdout);
    n=read(),m=read();
    for (int i=1; i<=n; i++) p[i].d[0]=read(),p[i].d[1]=read(); 
    KDT.init();
    for (int i=1; i<=m; i++) 
        {
            int opt=read(),x=read(),y=read();
            if (opt==1) KDT.insert(PointNode(x,y));
            if (opt==2) printf("%d\n",KDT.query(PointNode(x,y)));
        }
    return 0;
}

模板是参考的zky学长的,zky学长好神%%%

posted @ 2016-05-23 07:18  DaD3zZ  阅读(363)  评论(0编辑  收藏  举报