BZOJ2648:SJY摆棋子

浅谈\(K-D\) \(Tree\)https://www.cnblogs.com/AKMer/p/10387266.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2648

\(K-D\) \(Tree\)最近点查询裸题,注意先把所有点建好再一个个激活。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
 
const int maxn=5e5+5,inf=2e9;
 
int n,m,pps,ans,node[maxn];
 
int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}
 
struct query {
    int opt,x,y;
}q[maxn];
 
struct kd_tree {
    int cnt,root;
	int fa[maxn<<1];
 
    struct point {
        int c[2],mn[2],mx[2],id,ls,rs;
 
        point() {}
 
        point(int _x,int _y,int _id) {
            c[0]=_x,c[1]=_y,id=_id;
            if(id<=n)mn[0]=mx[0]=c[0],mn[1]=mx[1]=c[1];
            else mn[0]=mn[1]=inf,mx[0]=mx[1]=-inf;
			ls=rs=0;
        }
 
        bool operator<(const point &a)const {
            return c[pps]<a.c[pps];
        }
    }p[maxn<<1];
 
    void update(int u) {
        int ls=p[u].ls,rs=p[u].rs;
        for(int i=0;i<2;i++) {
            int mn=min(p[ls].mn[i],p[rs].mn[i]);
            p[u].mn[i]=min(p[u].mn[i],mn);
            int mx=max(p[ls].mx[i],p[rs].mx[i]);
            p[u].mx[i]=max(p[u].mx[i],mx);
        }
    }
 
    int build(int l,int r,int cmp) {
        int mid=(l+r)>>1,u=mid;pps=cmp;
        nth_element(p+l,p+mid,p+r+1);
		if(p[u].id>n)node[p[u].id-n]=u;
        if(l<mid)fa[p[u].ls=build(l,mid-1,cmp^1)]=u;
        if(r>mid)fa[p[u].rs=build(mid+1,r,cmp^1)]=u;
        update(u);
        return u;
    }
 
    void prepare() {
        p[0]=point(0,0,2e9);
        for(int i=1;i<=n;i++) {
            int x=read(),y=read();
            p[i]=point(x,y,i);
        }
        for(int i=1;i<=m;i++) {
            int opt=read(),x=read(),y=read();
            q[i].opt=opt,q[i].x=x,q[i].y=y;
            if(opt==1)p[++cnt]=point(x,y,n+i);
        }
        root=build(1,cnt,0);
    }
 
    void arouse(int u) {
		p[u].mn[0]=p[u].mx[0]=p[u].c[0];
		p[u].mn[1]=p[u].mx[1]=p[u].c[1];
		while(fa[u])update(u),u=fa[u];
		update(u);
    }
 
    int dis(int id,int x,int y) {
        int res=0;
        if(x<p[id].mn[0])res+=p[id].mn[0]-x;
        if(x>p[id].mx[0])res+=x-p[id].mx[0];
        if(y<p[id].mn[1])res+=p[id].mn[1]-y;
        if(y>p[id].mx[1])res+=y-p[id].mx[1];
        return res;
    }
 
    void query(int u,int x,int y,int id) {
        if(p[u].id<id)ans=min(ans,abs(x-p[u].c[0])+abs(y-p[u].c[1]));
        int dl=p[u].ls?dis(p[u].ls,x,y):inf;
        int dr=p[u].rs?dis(p[u].rs,x,y):inf;
        if(dl<dr) {
            if(dl<ans)query(p[u].ls,x,y,id);
            if(dr<ans)query(p[u].rs,x,y,id);
        }
        else {
            if(dr<ans)query(p[u].rs,x,y,id);
            if(dl<ans)query(p[u].ls,x,y,id);
        }
    }
}T;
 
int main() {
    T.cnt=n=read(),m=read();
    T.prepare();
    for(int i=1;i<=m;i++) 
        if(q[i].opt==1)T.arouse(node[i]);
        else {
            ans=2e9;
            T.query(T.root,q[i].x,q[i].y,n+i);
            printf("%d\n",ans);
        }
    return 0;
}
posted @ 2019-02-17 17:16  AKMer  阅读(142)  评论(0编辑  收藏  举报