• luogu P6224 [BJWC2014]数据 KD-tree 标准板子 重构+二维平面内最近最远距离查询


    LINK:数据

    这是一个我写过的最标准的板子。

    重构什么的写的非常的标准 常数应该也算很小的。

    不过虽然过了题 我也不知道代码是否真的无误 反正我已经眼查三遍了...

    重构:建议先插入 插入过程中找到第一个不平衡的点再重构。

    最小距离查询剪枝:当前坐标为mn和mx中间的时候显然 最小距离可能为0 否则 为他们其中之一和当前坐标的差。

    最大距离查询剪枝:当前坐标和mn以及mx的最大距离差。

    const int MAXN=500010,K=2;
    const db alpha=0.75;
    int n,root,top,D,Q,cnt,ans;
    struct wy
    {
    	int d[K];
    	int mn[K],mx[K];
    	int sz,l,r;
    }t[MAXN];
    int q[MAXN];
    inline int cmp(int a,int b){return t[a].d[D]<t[b].d[D];}
    inline void update(int x)
    {
    	sz(x)=sz(l(x))+sz(r(x))+1;
    	for(int i=0;i<K;++i)
        {
            if(l(x))t[x].mx[i]=max(t[x].mx[i],t[l(x)].mx[i]),t[x].mn[i]=min(t[x].mn[i],t[l(x)].mn[i]);
            if(r(x))t[x].mx[i]=max(t[x].mx[i],t[r(x)].mx[i]),t[x].mn[i]=min(t[x].mn[i],t[r(x)].mn[i]);
        }
    }
    inline int build(int l,int r,int k)
    {
    	if(l>r)return 0;
    	int mid=(l+r)>>1;D=k;
    	nth_element(q+l,q+mid,q+1+r,cmp);
    	int x=q[mid];
    	for(int i=0;i<K;++i)t[x].mx[i]=t[x].mn[i]=t[x].d[i];
    	l(x)=build(l,mid-1,(k+1)%K);
    	r(x)=build(mid+1,r,(k+1)%K);
    	update(x);return x;
    }
    inline void erase(int x)
    {
    	if(!x)return;q[++top]=x;
    	erase(l(x));erase(r(x));
    }
    inline void rebuild(int &x,int k)
    {
    	top=0;erase(x);
    	x=build(1,top,k);
    }
    inline void insert(int &p,int k,int flag)
    {
    	if(!p)
    	{
    		p=++cnt;sz(p)=1;
    		for(int i=0;i<K;++i)t[p].mx[i]=t[p].mn[i]=t[p].d[i]=q[i];
    		return;
    	}
    	int mark=0;
    	if(q[k]<t[p].d[k])
    	{
    		if((sz(l(p))+1)>=alpha*(sz(p)+1))mark=1;
    		insert(l(p),(k+1)%K,flag|mark);
    	}
    	else
    	{
    		if((sz(r(p)+1)>=alpha*(sz(p)+1)))mark=1;
    		insert(r(p),(k+1)%K,flag|mark);
    	}
    	if(!flag&&mark)rebuild(p,k);
    	update(p);
    }
    inline int dis(int x)
    {
    	int cnt=0;
    	rep(0,K-1,i)cnt+=abs(t[x].d[i]-q[i]);
    	return cnt;
    }
    inline int dismin(int x)//查当前离节点最近的距离
    {
    	int cnt=0;
    	rep(0,K-1,i)if(q[i]<t[x].mn[i])cnt+=t[x].mn[i]-q[i];
    	else if(q[i]>t[x].mx[i])cnt+=q[i]-t[x].mx[i];
    	return cnt;
    }
    inline void ask_min(int x)
    {
    	ans=min(ans,dis(x));
    	int L=dismin(l(x));
    	int R=dismin(r(x));
    	if(L<R)
    	{
    		if(L<ans&&l(x))ask_min(l(x));
    		if(R<ans&&r(x))ask_min(r(x));
    	}
    	else
    	{
    		if(R<ans&&r(x))ask_min(r(x));
    		if(L<ans&&l(x))ask_min(l(x));
    	}
    }
    inline int dismax(int x)
    {
    	int cnt=0;
    	rep(0,K-1,i)cnt+=max(abs(q[i]-t[x].mn[i]),abs(q[i]-t[x].mx[i]));
    	return cnt;
    }
    inline void ask_max(int x)
    {
    	ans=max(ans,dis(x));
    	int L=dismax(l(x));
    	int R=dismax(r(x));
    	if(L>R)
    	{
    		if(L>ans&&l(x))ask_max(l(x));
    		if(R>ans&&r(x))ask_max(r(x));
    	}
    	else
    	{
    		if(R>ans&&r(x))ask_max(r(x));
    		if(L>ans&&l(x))ask_max(l(x));
    	}
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);cnt=n;
    	rep(1,n,i)
    	{
    		int get(x);int get(y);
    		t[i].d[0]=x;t[i].d[1]=y;
    		q[i]=i;
    	}
    	root=build(1,n,0);
    	get(Q);
    	rep(1,Q,i)
    	{
    		int op;
    		get(op);get(q[0]);get(q[1]);
    		if(op==0)insert(root,0,0);
    		if(op==1)
    		{
    			ans=INF;
    			ask_min(root);
    			put(ans);
    		}
    		if(op==2)
    		{
    			ans=-INF;
    			ask_max(root);
    			put(ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    二叉树
    基础1
    tcp/udp
    异步io模块(自定义)
    select+异步
    异步发送请求的几种方式
    多线程,进程实现并发请求
    位解包运算
    从前端程序员的视角看小程序的稳定性保障
    运行node 报错 throw er; // Unhandled 'error' event
  • 原文地址:https://www.cnblogs.com/chdy/p/12727807.html
Copyright © 2020-2023  润新知