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

时间:2023-03-09 00:40:06
BZOJ2716: [Violet 3]天使玩偶(KD-Tree)

Description

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

Input

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

Output

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

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

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const int D=;
const int maxn=;
const double alpha=0.75;
int here;
struct KD_pnt{
int v[D];
bool friend operator < (KD_pnt x,KD_pnt y)
{
return x.v[here]<y.v[here];
}
}p[maxn];
struct KD_trnt{
KD_pnt val;
KD_pnt mx;
KD_pnt mn;
int ls;
int rs;
int wgt;
}kt[maxn],stdkt;
int n,m;
int ans;
int top;
int siz;
int root;
int bin[maxn];
inline int read(void)
{
int anss=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')
f=-f;
ch=getchar();
}
while(ch>=''&&ch<='')
{
anss=anss*+ch-'';
ch=getchar();
}
return anss*f;
}
int newp(void)
{
if(top)
return bin[top--];
return ++siz;
}
void Trash(int spc)
{
bin[++top]=spc;
return ;
}
void apply(int &spc)
{
spc=newp();
kt[spc]=stdkt;
return ;
}
int Dist(KD_pnt a,KD_pnt b)
{
int ans=;
for(int i=;i<D;i++)
ans+=std::abs(a.v[i]-b.v[i]);
return ans;
}
int assess(KD_pnt a,int spc)
{
int ans=;
for(int i=;i<D;i++)
ans+=std::max(,a.v[i]-kt[spc].mx.v[i])+std::max(,kt[spc].mn.v[i]-a.v[i]);
return ans;
}
void pushup(int spc)
{
kt[spc].mx=kt[spc].mn=kt[spc].val;
if(kt[spc].ls)
{
kt[spc].mx.v[]=std::max(kt[spc].mx.v[],kt[kt[spc].ls].mx.v[]);
kt[spc].mn.v[]=std::min(kt[spc].mn.v[],kt[kt[spc].ls].mn.v[]);
kt[spc].mx.v[]=std::max(kt[spc].mx.v[],kt[kt[spc].ls].mx.v[]);
kt[spc].mn.v[]=std::min(kt[spc].mn.v[],kt[kt[spc].ls].mn.v[]);
}
if(kt[spc].rs)
{
kt[spc].mx.v[]=std::max(kt[spc].mx.v[],kt[kt[spc].rs].mx.v[]);
kt[spc].mn.v[]=std::min(kt[spc].mn.v[],kt[kt[spc].rs].mn.v[]);
kt[spc].mx.v[]=std::max(kt[spc].mx.v[],kt[kt[spc].rs].mx.v[]);
kt[spc].mn.v[]=std::min(kt[spc].mn.v[],kt[kt[spc].rs].mn.v[]);
}
kt[spc].wgt=+kt[kt[spc].ls].wgt+kt[kt[spc].rs].wgt;
return ;
}
void build(int l,int r,int dim,int &spc)
{
if(l>r)
{
spc=;
return ;
}
apply(spc);
here=dim;
int mid=(l+r)>>;
std::nth_element(p+l,p+mid,p+r+);
kt[spc].val=p[mid];
build(l,mid-,dim^,kt[spc].ls);
build(mid+,r,dim^,kt[spc].rs);
pushup(spc);
return ;
}
void Destory(int spc,int sta)
{
if(kt[spc].ls)
Destory(kt[spc].ls,sta);
p[sta+kt[kt[spc].ls].wgt+]=kt[spc].val;
Trash(spc);
if(kt[spc].rs)
Destory(kt[spc].rs,sta+kt[kt[spc].ls].wgt+);
return ;
}
bool imbalance(int root)
{
return ((double)(std::max(kt[kt[root].ls].wgt,kt[kt[root].rs].wgt))>alpha*(double)(kt[root].wgt));
}
void rebuild(int &spc,int dim)
{
Destory(spc,);
build(,kt[spc].wgt,dim,spc);
return ;
}
void Insert(int &spc,KD_pnt x,int dim)
{
if(!spc)
{
apply(spc);
kt[spc].val=x;
pushup(spc);
return ;
}
if(kt[spc].val.v[dim]<x.v[dim])
Insert(kt[spc].rs,x,dim^);
else
Insert(kt[spc].ls,x,dim^);
pushup(spc);
if(imbalance(spc))
rebuild(spc,dim);
return ;
}
void Query(int spc,KD_pnt x)
{
if(!spc)
return ;
ans=std::min(ans,Dist(x,kt[spc].val));
int disls,disrs;
if(kt[spc].ls)
disls=assess(x,kt[spc].ls);
else
disls=0x7f7f7f7f;
if(kt[spc].rs)
disrs=assess(x,kt[spc].rs);
else
disrs=0x7f7f7f7f;
if(disls<disrs)
{
if(disls<ans)
Query(kt[spc].ls,x);
if(disrs<ans)
Query(kt[spc].rs,x);
}else{
if(disrs<ans)
Query(kt[spc].rs,x);
if(disls<ans)
Query(kt[spc].ls,x);
}
return ;
}
int main()
{
n=read();
m=read();
for(int i=;i<=n;i++)
p[i].v[]=read(),p[i].v[]=read();;
build(,n,,root);
while(m--)
{
int cmd;
KD_pnt x;
ans=0x7f7f7f7f;
cmd=read();
x.v[]=read();
x.v[]=read();
if(cmd==)
Insert(root,x,);
else{
Query(root,x);
printf("%d\n",ans);
}
}
return ;
}