K-D tree 重学

K-D tree 重学

仍然依旧是粘板子

Luogu2479 捉迷藏

code
#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=5e5+5;
int n,comp;
int minn[N],maxn[N],ans;
struct POT{
	int d[2],id;
	bool operator < (POT a)const{
		return a.d[comp]>d[comp];
	}
}sca[N];
int DIS(POT x,POT y){
	return abs(x.d[0]-y.d[0])+abs(x.d[1]-y.d[1]);
}
struct KD_TREE{
	struct KD_POT{
		POT x;
		int ls,rs;
		int mn[2],mx[2];
	}tr[N];
	int rt,seg;
	POT res;
	void pushup(int x){
		int ls=tr[x].ls,rs=tr[x].rs;
		for(re i=0;i<=1;i++){
			tr[x].mn[i]=tr[x].mx[i]=tr[x].x.d[i];
			if(ls){
				tr[x].mn[i]=min(tr[x].mn[i],tr[ls].mn[i]);
				tr[x].mx[i]=max(tr[x].mx[i],tr[ls].mx[i]);
			}
			if(rs){
				tr[x].mn[i]=min(tr[x].mn[i],tr[rs].mn[i]);
				tr[x].mx[i]=max(tr[x].mx[i],tr[rs].mx[i]);
			}
		}
	}
	void build(int &x,int l,int r,int f){
		int mid=l+r>>1;
		comp=f;
		nth_element(sca+l,sca+mid,sca+r+1);
		x=++seg;
		tr[x].x=sca[mid];
		if(l<mid)build(tr[x].ls,l,mid-1,f^1);
		if(r>mid)build(tr[x].rs,mid+1,r,f^1);
		pushup(x);return ;
	}
	int get_max(int x,POT y){
		int ret=0;
		for(re i=0;i<=1;i++){
			ret+=max(abs(y.d[i]-tr[x].mn[i]),abs(tr[x].mx[i]-y.d[i]));
		}
		return ret;
	}
	int get_min(int x,POT y){
		int ret=0;
		for(re i=0;i<=1;i++){
			//int tmp=min(abs(y.d[i]-tr[x].mn[i]),abs(tr[x].mx[i]-y.d[i]));
			ret+=max(tr[x].mn[i]-y.d[i],0);
			ret+=max(y.d[i]-tr[x].mx[i],0);
		}
		return ret;
	}
	void query_max(int x,POT y){
		if(!x)return ;
		if(DIS(tr[x].x,y)>maxn[y.id]&&tr[x].x.id!=y.id){
			maxn[y.id]=DIS(tr[x].x,y);
			res=tr[x].x;
		}
		int ls=tr[x].ls,rs=tr[x].rs,dl=0,dr=0;
		if(ls)dl=get_max(ls,y);
		if(rs)dr=get_max(rs,y);
		if(dl>dr){
			if(dl>maxn[y.id])query_max(ls,y);
			if(dr>maxn[y.id])query_max(rs,y);
		}
		else{
			if(dr>maxn[y.id])query_max(rs,y);
			if(dl>maxn[y.id])query_max(ls,y);
		}
		return ;
	}
	void query_min(int x,POT y){
		if(!x)return ;
		if(DIS(tr[x].x,y)<minn[y.id]&&tr[x].x.id!=y.id){
			minn[y.id]=DIS(tr[x].x,y);
			res=tr[x].x;
		}
		int ls=tr[x].ls,rs=tr[x].rs,dl=0x3f3f3f3f,dr=0x3f3f3f3f;
		if(ls)dl=get_min(ls,y);
		if(rs)dr=get_min(rs,y);
		if(dl<dr){
			if(dl<minn[y.id])query_min(ls,y);
			if(dr<minn[y.id])query_min(rs,y);
		}
		else{
			if(dr<minn[y.id])query_min(rs,y);
			if(dl<minn[y.id])query_min(ls,y);
		}
		return ;
	}
}kd;
signed main(){
	scanf("%d",&n);
	for(re i=1;i<=n;i++){
		scanf("%d%d",&sca[i].d[0],&sca[i].d[1]),sca[i].id=i;
	}
	memset(minn,0x7f,sizeof(minn));
	kd.build(kd.rt,1,n,0);
	ans=0x3f3f3f3f;
	for(re i=1;i<=n;i++){
		kd.query_max(kd.rt,sca[i]);
		maxn[kd.res.id]=maxn[sca[i].id];
		kd.query_min(kd.rt,sca[i]);
		minn[kd.res.id]=minn[sca[i].id];
		ans=min(ans,maxn[sca[i].id]-minn[sca[i].id]);
	}
	printf("%d",ans);
}

Luogu4169 SJY摆棋子

code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int inf=0x3f3f3f3f;
const int N=1e6+5;
const double al=0.7;
int n,m,comp;
struct P{int d[2];P(){}P(int x,int y){d[0]=x;d[1]=y;}}sca[N];
bool com(P a,P b){return a.d[comp]<b.d[comp];}
int dis(P a,P b){return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);}
struct KD{
    struct POT{
        P x;int ls,rs,siz;
        int mn[2],mx[2];
    }tr[N];
    int rt,seg,res,ji[N],cnt;
    void pushup(int x){
        tr[x].siz=tr[tr[x].ls].siz+tr[tr[x].rs].siz+1;
        fo(i,0,1){
            tr[x].mn[i]=tr[x].mx[i]=tr[x].x.d[i];
            if(tr[x].ls){
                tr[x].mn[i]=min(tr[x].mn[i],tr[tr[x].ls].mn[i]);
                tr[x].mx[i]=max(tr[x].mx[i],tr[tr[x].ls].mx[i]);
            }
            if(tr[x].rs){
                tr[x].mn[i]=min(tr[x].mn[i],tr[tr[x].rs].mn[i]);
                tr[x].mx[i]=max(tr[x].mx[i],tr[tr[x].rs].mx[i]);
            }
        }
    }
    void clear(int x){
        tr[x].ls=tr[x].rs=0;tr[x].siz=1;
        tr[x].mn[0]=tr[x].mx[0]=tr[x].x.d[0];
        tr[x].mn[1]=tr[x].mx[1]=tr[x].x.d[1];
    }
    void build(int &x,int l,int r,int f){
        int mid=l+r>>1;x=ji[mid];comp=f;
        nth_element(sca+l,sca+mid,sca+r+1,com);
        tr[x].x=sca[mid];pushup(x);
        if(l<mid)build(tr[x].ls,l,mid-1,f^1);
        if(r>mid)build(tr[x].rs,mid+1,r,f^1);
        pushup(x);return ;
    }
    void pia(int x){
        ji[++cnt]=x;sca[cnt]=tr[x].x;
        if(tr[x].ls)pia(tr[x].ls);
        if(tr[x].rs)pia(tr[x].rs);
    }
    bool need(int x){
        if(tr[tr[x].ls].siz>tr[x].siz*al)return true;
        if(tr[tr[x].rs].siz>tr[x].siz*al)return true;
        return false;
    }
    void ins(int &x,int f,P v){
        if(!x){
            x=++seg;tr[x].x=v;
            pushup(x);return ;
        }
        if(v.d[f]<=tr[x].x.d[f])ins(tr[x].ls,f^1,v);
        else ins(tr[x].rs,f^1,v);
        if(need(x)){cnt=0;pia(x);build(x,1,cnt,f);}
        pushup(x);return ;
    }
    int get_min(int x,P v){
        int ret=0;
        fo(i,0,1){
            ret+=max(tr[x].mn[i]-v.d[i],0);
            ret+=max(v.d[i]-tr[x].mx[i],0);
        }
        return ret;
    }
    void query(int x,P v){
        if(!x)return ;
        if(dis(tr[x].x,v)<res)res=dis(tr[x].x,v);
        int dl=inf,dr=inf;
        if(tr[x].ls)dl=get_min(tr[x].ls,v);
        if(tr[x].rs)dr=get_min(tr[x].rs,v);
        if(dl<dr){
            if(dl<res)query(tr[x].ls,v);
            if(dr<res)query(tr[x].rs,v);
        }
        else{
            if(dr<res)query(tr[x].rs,v);
            if(dl<res)query(tr[x].ls,v);
        }
    }
}kd;
signed main(){
    kd.seg=n=read();m=read();
    fo(i,1,n)sca[i].d[0]=read(),sca[i].d[1]=read(),kd.ji[i]=i;
    kd.build(kd.rt,1,n,0);
    fo(i,1,m){
        int tp=read(),x=read(),y=read();
        if(tp==1)kd.ins(kd.rt,0,P(x,y));
        else {
            kd.res=inf;kd.query(kd.rt,P(x,y));
            printf("%d\n",kd.res);
        }
    }
}
上一篇:题解 P7706 「Wdsr-2.7」文文的摄影布置


下一篇:linux常用命令