您的位置:首页 > 其它

[bzoj2648/2716]SJY摆棋子

2017-03-31 15:01 316 查看
平面上有n个点,要求支持插入一个点和查询一个点的最近点距离 n,m<=500000

用kdtree实现,但是复杂度貌似没法保证.....(莫名加了替罪羊重建更慢了...)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 2000000000
#define MN 1000000
using namespace std;
inline 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;
}
int n,now,m;
inline int abs(int x){return x<0?-x:x;}
struct P{
int d[2],mx[2],mn[2],l,r;
int& operator[](int x){return d[x];}
bool operator<(const P&x)const{return d[now]<x.d[now];}
friend int dis(P x,P y){return abs(x.d[0]-y.d[0])+abs(x.d[1]-y.d[1]);}
}t[MN+5];

struct KD_TREE{
P p[MN+5],T;int ans;
void update(int x)
{
int l=p[x].l,r=p[x].r;
for(int i=0;i<2;i++)
{
if(l) p[x].mn[i]=min(p[x].mn[i],p[l].mn[i]),
p[x].mx[i]=max(p[x].mx[i],p[l].mx[i]);
if(r) p[x].mn[i]=min(p[x].mn[i],p[r].mn[i]),
p[x].mx[i]=max(p[x].mx[i],p[r].mx[i]);
}
}
void ins(int x,int th)
{
if(T>=p[x])
{
if(p[x].r) ins(p[x].r,th^1);
else
{
int r=p[x].r=++n;p[r]=T;
for(int i=0;i<2;i++)
p[r].mn[i]=p[r].mx[i]=T[i];
}
}
else
{
if(p[x].l) ins(p[x].l,th^1);
else
{
int l=p[x].l=++n;p[l]=T;
for(int i=0;i<2;i++)
p[l].mn[i]=p[l].mx[i]=T[i];
}
}
update(x);
}
int getmn(P x)
{
int sum=0;
for(int i=0;i<2;i++)
{
sum+=max(x.mn[i]-T[i],0);
sum+=max(T[i]-x.mx[i],0);
}
return sum;
}
int build(int l,int r,int th)
{
int mid=l+r>>1;now=th;
nth_element(t+l,t+mid,t+r+1);
p[mid]=t[mid];
for(int i=0;i<2;i++)
p[mid].mx[i]=p[mid].mn[i]=p[mid][i];
if(l<mid) p[mid].l=build(l,mid-1,th^1);
if(mid<r) p[mid].r=build(mid+1,r,th^1);
update(mid);
return mid;
}
void querymn(int k)
{
ans=min(ans,dis(p[k],T));
int dl=INF,dr=INF;
if(p[k].l) dl=getmn(p[p[k].l]);
if(p[k].r) dr=getmn(p[p[k].r]);
if(dl>dr)
{
if(dr<ans) querymn(p[k].r);
if(dl<ans) querymn(p[k].l);
}
else
{
if(dl<ans) querymn(p[k].l);
if(dr<ans) querymn(p[k].r);
}
}
}kd;
int rt,ans=INF;

int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
t[i][0]=read(),t[i][1]=read();
rt=kd.build(1,n,0);
for(int i=1;i<=m;i++)
{
int op=read();kd.T[0]=read();kd.T[1]=read();
if(op==1) kd.ins(rt,0);
else
{
kd.ans=INF;kd.querymn(rt);
printf("%d\n",kd.ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: