BZOJ2716: [Violet 3]天使玩偶(KD-Tree)

 

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

解题思路:

样例好良心。

写CDQ写腻了,这道题还是学一学KD-Tree吧。

KD-Tree,可以认为是在K维空间上二分答案。

将二分得到的顺序建树。

这样的结构很难支持修改,所以暴力插入。

应用替罪羊的想法,不优秀就暴力重建。

时间复杂度玄学。(维护矩形曼哈顿距离)

非常开心地AC

代码:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 typedef long long lnt;
  5 const int D=2;
  6 const int maxn=1000000;
  7 const double alpha=0.75;
  8 int here;
  9 struct KD_pnt{
 10     int v[D];
 11     bool friend operator < (KD_pnt x,KD_pnt y)
 12     {
 13         return x.v[here]<y.v[here];
 14     }
 15 }p[maxn];
 16 struct KD_trnt{
 17     KD_pnt val;
 18     KD_pnt mx;
 19     KD_pnt mn;
 20     int ls;
 21     int rs;
 22     int wgt;
 23 }kt[maxn],stdkt;
 24 int n,m;
 25 int ans;
 26 int top;
 27 int siz;
 28 int root;
 29 int bin[maxn];
 30 inline int read(void)
 31 {
 32     int anss=0,f=1;
 33     char ch=getchar();
 34     while(ch<'0'||ch>'9')
 35     {
 36         if(ch=='-')
 37             f=-f;
 38         ch=getchar();
 39     }
 40     while(ch>='0'&&ch<='9')
 41     {
 42         anss=anss*10+ch-'0';
 43         ch=getchar();
 44     }
 45     return anss*f;
 46 }
 47 int newp(void)
 48 {
 49     if(top)
 50         return bin[top--];
 51     return ++siz;
 52 }
 53 void Trash(int spc)
 54 {
 55     bin[++top]=spc;
 56     return ;
 57 }
 58 void apply(int &spc)
 59 {
 60     spc=newp();
 61     kt[spc]=stdkt;
 62     return ;
 63 }
 64 int Dist(KD_pnt a,KD_pnt b)
 65 {
 66     int ans=0;
 67     for(int i=0;i<D;i++)
 68         ans+=std::abs(a.v[i]-b.v[i]);
 69     return ans;
 70 }
 71 int assess(KD_pnt a,int spc)
 72 {
 73     int ans=0;
 74     for(int i=0;i<D;i++)
 75         ans+=std::max(0,a.v[i]-kt[spc].mx.v[i])+std::max(0,kt[spc].mn.v[i]-a.v[i]);
 76     return ans;
 77 }
 78 void pushup(int spc)
 79 {
 80     kt[spc].mx=kt[spc].mn=kt[spc].val;
 81     if(kt[spc].ls)
 82     {
 83         kt[spc].mx.v[0]=std::max(kt[spc].mx.v[0],kt[kt[spc].ls].mx.v[0]);
 84         kt[spc].mn.v[0]=std::min(kt[spc].mn.v[0],kt[kt[spc].ls].mn.v[0]);
 85         kt[spc].mx.v[1]=std::max(kt[spc].mx.v[1],kt[kt[spc].ls].mx.v[1]);
 86         kt[spc].mn.v[1]=std::min(kt[spc].mn.v[1],kt[kt[spc].ls].mn.v[1]);
 87     }
 88     if(kt[spc].rs)
 89     {
 90         kt[spc].mx.v[0]=std::max(kt[spc].mx.v[0],kt[kt[spc].rs].mx.v[0]);
 91         kt[spc].mn.v[0]=std::min(kt[spc].mn.v[0],kt[kt[spc].rs].mn.v[0]);
 92         kt[spc].mx.v[1]=std::max(kt[spc].mx.v[1],kt[kt[spc].rs].mx.v[1]);
 93         kt[spc].mn.v[1]=std::min(kt[spc].mn.v[1],kt[kt[spc].rs].mn.v[1]);
 94     }
 95     kt[spc].wgt=1+kt[kt[spc].ls].wgt+kt[kt[spc].rs].wgt;
 96     return ;
 97 }
 98 void build(int l,int r,int dim,int &spc)
 99 {
100     if(l>r)
101     {
102         spc=0;
103         return ;
104     }
105     apply(spc);
106     here=dim;
107     int mid=(l+r)>>1;
108     std::nth_element(p+l,p+mid,p+r+1);
109     kt[spc].val=p[mid];
110     build(l,mid-1,dim^1,kt[spc].ls);
111     build(mid+1,r,dim^1,kt[spc].rs);
112     pushup(spc);
113     return ;
114 }
115 void Destory(int spc,int sta)
116 {
117     if(kt[spc].ls)
118         Destory(kt[spc].ls,sta);
119     p[sta+kt[kt[spc].ls].wgt+1]=kt[spc].val;
120     Trash(spc);
121     if(kt[spc].rs)
122         Destory(kt[spc].rs,sta+kt[kt[spc].ls].wgt+1);
123     return ;
124 }
125 bool imbalance(int root)
126 {
127     return ((double)(std::max(kt[kt[root].ls].wgt,kt[kt[root].rs].wgt))>alpha*(double)(kt[root].wgt));
128 }
129 void rebuild(int &spc,int dim)
130 {
131     Destory(spc,0);
132     build(1,kt[spc].wgt,dim,spc);
133     return ;
134 }
135 void Insert(int &spc,KD_pnt x,int dim)
136 {
137     if(!spc)
138     {
139         apply(spc);
140         kt[spc].val=x;
141         pushup(spc);
142         return ;
143     }
144     if(kt[spc].val.v[dim]<x.v[dim])
145         Insert(kt[spc].rs,x,dim^1);
146     else
147         Insert(kt[spc].ls,x,dim^1);
148     pushup(spc);
149     if(imbalance(spc))
150         rebuild(spc,dim);
151     return ;
152 }
153 void Query(int spc,KD_pnt x)
154 {
155     if(!spc)
156         return ;
157     ans=std::min(ans,Dist(x,kt[spc].val));
158     int disls,disrs;
159     if(kt[spc].ls)
160         disls=assess(x,kt[spc].ls);
161     else
162         disls=0x7f7f7f7f;
163     if(kt[spc].rs)
164         disrs=assess(x,kt[spc].rs);
165     else
166         disrs=0x7f7f7f7f;
167     if(disls<disrs)
168     {
169         if(disls<ans)
170             Query(kt[spc].ls,x);
171         if(disrs<ans)
172             Query(kt[spc].rs,x);
173     }else{
174         if(disrs<ans)
175             Query(kt[spc].rs,x);
176         if(disls<ans)
177             Query(kt[spc].ls,x);
178     }
179     return ;
180 }
181 int main()
182 {
183     n=read();
184     m=read();
185     for(int i=1;i<=n;i++)
186         p[i].v[0]=read(),p[i].v[1]=read();;
187     build(1,n,0,root);
188     while(m--)
189     {
190         int cmd;
191         KD_pnt x;
192         ans=0x7f7f7f7f;
193         cmd=read();
194         x.v[0]=read();
195         x.v[1]=read();
196         if(cmd==1)
197             Insert(root,x,0);
198         else{
199             Query(root,x);
200             printf("%d\n",ans);
201         }
202     }
203     return 0;
204 }

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/10115995.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值