• kd-tree


    纪念oi路上第一颗kd-tree

    Hide and Seek

    说说主要思想,考虑二叉搜索树来统计答案,玄学乱搞的地方就是减枝了。通过不断换维(不一定一直换,只要保证时间空间都尽量优就行),用<algorithm>库中的nth_element来找到中位数式的元素,此元素就是二叉搜索树对应的元素。最大值用A*思想减支,最小值用边界判断。还有值得学习的地方是判断先搜左儿子还是右儿子

    /*
    	从直系的直系的学长颓来的板子
    */
    #include<algorithm>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #define MAXN 100010
    #define INF 0x7fffffff
    using namespace std;
    int opt;
    struct ww{
    	int wg[2];
    	friend bool operator <(const ww &a,const ww &b){
    		return a.wg[opt]<b.wg[opt];
    	}
    }wen[MAXN];
    inline int minn(int a,int b){return a<b?a:b; }
    inline int maxn(int a,int b){return a>b?a:b; }
    int n;
    struct KDTREE{
    	int num,root,res;
    	struct TREE{
    		ww wen;
    		int ls,rs;
    		int mx[2],mn[2];
    		#define ls(u) (tr[u].ls)
    		#define rs(u) (tr[u].rs)
    	}tr[MAXN];
    	inline int mht(ww a,TREE b){
    		return abs(a.wg[0]-b.wen.wg[0])+abs(a.wg[1]-b.wen.wg[1]); 
    	}
    	inline int mxdis(ww a,TREE b){
    		int x=maxn(abs(a.wg[0]-b.mn[0]),abs(a.wg[0]-b.mx[0]));
    		int y=maxn(abs(a.wg[1]-b.mn[1]),abs(a.wg[1]-b.mx[1]));
    		return x+y;
    	}
    	inline int mndis(ww a,TREE b){//只减掉了在边界外的树枝
    		int x=maxn(b.mn[0]-a.wg[0],0)+maxn(a.wg[0]-b.mx[0],0);
    		int y=maxn(b.mn[1]-a.wg[1],0)+maxn(a.wg[1]-b.mx[1],0);
    		return x+y;
    	}
    	void qw_mx(ww a,int u,int knd){
    		if(!u)return ;int tmp;
    		if((tmp=mht(a,tr[u]))>res)res=tmp;
    		int lch=ls(u),rch=rs(u);
    		if(a.wg[knd]<tr[lch].wen.wg[knd])swap(lch,rch);//
    		if(mxdis(a,tr[lch])>res)qw_mx(a,lch,knd^1);
    		if(mxdis(a,tr[rch])>res)qw_mx(a,rch,knd^1);
    	}
    	int qw_mx(ww a){
    		res=-INF;
    		qw_mx(a,root,0);
    		return res;
    	}
    	void qw_mn(ww a,int u,int knd){
    		//printf("u=%d knd=%d
    ",u,knd);
    		if(!u)return ;int tmp;
    		if((tmp=mht(a,tr[u]))<res&&tmp)res=tmp;
    		//cout<<tmp<<endl;
    		int lch=ls(u),rch=rs(u);
    		//cout<<lch<<" "<<rch<<endl;
    		if(a.wg[knd]>tr[lch].wen.wg[knd])swap(lch,rch);//
    		if(mndis(a,tr[lch])<res)qw_mn(a,lch,knd^1);
    		if(mndis(a,tr[rch])<res)qw_mn(a,rch,knd^1);
    	}
    	int qw_mn(ww a){
    		//cout<<a.wg[0]<<" "<<a.wg[1]<<endl;
    		res=INF;
    		qw_mn(a,root,0);
    		//cout<<"STO"<<endl;
    		return res;
    	}
    	void up(int u){
    		if(ls(u))
    			for(int i=0;i<2;++i){
    				tr[u].mn[i]=minn(tr[u].mn[i],tr[ls(u)].mn[i]);
    				tr[u].mx[i]=maxn(tr[u].mx[i],tr[ls(u)].mx[i]);
    			}
    		if(rs(u))
    			for(int i=0;i<2;++i){
    				tr[u].mn[i]=minn(tr[u].mn[i],tr[rs(u)].mn[i]);
    				tr[u].mx[i]=maxn(tr[u].mx[i],tr[rs(u)].mx[i]);
    			}
    	}
    	void build(int &u,int l,int r,int knd){
    		if(r<l)return ;
    		u=++num;opt=knd;
    		int mid=l+r>>1;
    		nth_element(wen+l,wen+mid,wen+r+1);
    		tr[u].wen=wen[mid];
    		for(int i=0;i<2;++i)
    			tr[u].mn[i]=tr[u].mx[i]=wen[mid].wg[i];
    		build(ls(u),l,mid-1,knd^1); 
    		build(rs(u),mid+1,r,knd^1);
    		up(u);
    		//cout<<u<<" "<<tr[u].wen.wg[0]<<" "<<tr[u].wen.wg[1]<<endl;
    		//cout<<tr[u].mn[0]<<" "<<tr[u].mn[1]<<" "<<tr[u].mx[0]<<" "<<tr[u].mx[1]<<endl;
    	}
    	void build(){
    		root=num=0;
    		build(root,1,n,0);
    	}
    }QwQ;
    int ans=INF;
    int main(){
    //	freopen("da.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    		scanf("%d%d",&wen[i].wg[0],&wen[i].wg[1]);
    	QwQ.build();
    	for(int i=1;i<=n;++i){
    		ans=minn(ans,QwQ.qw_mx(wen[i])-QwQ.qw_mn(wen[i]));
    		//cout<<"HHHHHHHHH"<<QwQ.qw_mx(wen[i])<<" "<<QwQ.qw_mn(wen[i])<<endl;
    	}
    	printf("%d
    ",ans);
    }
    

     巧克力王国

    考虑两个减支:最小值比C小,不搞。最大值比C小,直接加上维护的子树权值和

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define MAXN 50010
    #define INF 0x7fffffff
    #define int long long
    #define reg register int
    using namespace std;
    inline int maxn(int a,int b){return a>b?a:b; }
    inline int minn(int a,int b){return a<b?a:b; }
    inline int read(){
    	int s=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar(); }
    	while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    	return s*w;
    }
    #define kd (read())
    int opt;
    struct ww{
    	int wg[2],h;
    	friend bool operator <(const ww &a,const ww &b){
    		return a.wg[opt]<b.wg[opt];
    	}
    }wen[MAXN];
    struct HH{int a,b,c;}hh;
    int n,m;
    struct KDTREE{
    	int root,num,res;
    	int zmx,zmn;
    	struct TR{
    		ww wen;
    		int mn[2],mx[2],ls,rs,sm;
    		#define ls(u) (tr[u].ls)
    		#define rs(u) (tr[u].rs)
    	}tr[MAXN];
    	inline int cal(HH x,TR y){
    		return x.a*y.wen.wg[0]+x.b*y.wen.wg[1];
    	}
    	inline void judge(HH x,TR y){
    		reg tmp;
    		zmx=-INF;zmn=INF;
    		tmp=y.mn[0]*x.a+y.mn[1]*x.b;
    		zmx=maxn(zmx,tmp);zmn=minn(zmn,tmp);
    		tmp=y.mn[0]*x.a+y.mx[1]*x.b;
    		zmx=maxn(zmx,tmp);zmn=minn(zmn,tmp);
    		tmp=y.mx[0]*x.a+y.mx[1]*x.b;
    		zmx=maxn(zmx,tmp);zmn=minn(zmn,tmp);
    		tmp=y.mx[0]*x.a+y.mn[1]*x.b;
    		zmx=maxn(zmx,tmp);zmn=minn(zmn,tmp);
    	}
    	void qw_sm(HH x,int u){
    		if(!u)return ;
    		if(cal(x,tr[u])<x.c)res+=tr[u].wen.h;
    		judge(x,tr[ls(u)]);
    		if(zmx<x.c)res+=tr[ls(u)].sm;
    		else if(zmn<x.c)qw_sm(x,ls(u));
    		judge(x,tr[rs(u)]);
    		if(zmx<x.c)res+=tr[rs(u)].sm;
    		else if(zmn<x.c)qw_sm(x,rs(u));
    	}
    	int qw_sm(HH x){
    		res=0;
    		qw_sm(x,root);
    		return res;
    	}
    	void up(int u){
    		if(ls(u)){
    			for(reg i=0;i<2;++i){
    				tr[u].mn[i]=minn(tr[u].mn[i],tr[ls(u)].mn[i]);
    				tr[u].mx[i]=maxn(tr[u].mx[i],tr[ls(u)].mx[i]);
    			}
    			tr[u].sm+=tr[ls(u)].sm;	
    		}
    		if(rs(u)){
    			for(reg i=0;i<2;++i){
    				tr[u].mn[i]=minn(tr[u].mn[i],tr[rs(u)].mn[i]);
    				tr[u].mx[i]=maxn(tr[u].mx[i],tr[rs(u)].mx[i]);
    			}
    			tr[u].sm+=tr[rs(u)].sm;	
    		}
    	}
    	void build(int &u,int l,int r,int knd){
    		if(r<l)return ;
    		u=++num;opt=knd;
    		int mid=l+r>>1;
    		nth_element(wen+l,wen+mid,wen+r+1);
    		tr[u].wen=wen[mid];
    		tr[u].sm=wen[mid].h;
    		for(reg i=0;i<2;++i)tr[u].mn[i]=tr[u].mx[i]=wen[mid].wg[i];
    		build(ls(u),l,mid-1,knd^1);build(rs(u),mid+1,r,knd^1);
    		up(u);
    	}
    	void build(){
    		root=num=0;
    		build(root,1,n,0);
    	}
    }QwQ;
    signed main(){
    //	freopen("da.in","r",stdin);
    	n=kd;m=kd;
    	for(reg i=1;i<=n;++i)
    		wen[i].wg[0]=kd,wen[i].wg[1]=kd,wen[i].h=kd;
    	QwQ.build();
    	for(reg i=1;i<=m;++i){
    		hh.a=kd,hh.b=kd,hh.c=kd;
    		printf("%lld
    ",QwQ.qw_sm(hh));
    	}
    }
    

     

  • 相关阅读:
    看了前辈缠中说禅及其反响,忍不住想说些东西
    利弗莫尔的操盘精华篇
    缠中说禅:教你炒股票108课(转载)
    评温斯坦的炒股书(非常重要,常看看)
    本散女2
    使用PHP-GTK编写一个windows桌面应用程序
    php.exe php-cgi.exe php-win.exe的区别
    php调试利器之phpdbg
    yaf框架安装配置
    phalcon框架安装
  • 原文地址:https://www.cnblogs.com/2018hzoicyf/p/11299423.html
Copyright © 2020-2023  润新知