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

时间:2023-03-10 08:03:48
【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

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

Input

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

Output

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

Sample Input


Sample Input

Sample Output


Sample Output

HINT

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

Source

Vani原创 欢迎移步 OJ2648

Solution

双倍经验题,KD Tree模板题

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

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

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

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

Code

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

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