zoukankan      html  css  js  c++  java
  • bzoj 1941: [Sdoi2010]Hide and Seek k-D Tree

    bzoj 1941: [Sdoi2010]Hide and Seek

    题目大意:

    给n个点,找出一个点使到这个点到其他点的最大曼哈顿距离与最小曼哈顿距离之差最小。

    题解

    我们可以分别枚举每个点
    然后对于该点查询到该点的最远点和最近点
    这个直接用K-D Tree就好了嘛..

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    inline int max(int a,int b,int c){return max(a,max(b,c));}
    inline int min(int a,int b,int c){return min(a,min(b,c));}
    const int maxn = 500010;
    const int dem = 2;
    struct Node{
    	Node *ch[2];
    	int pos[2],id;
    	int minn[2],maxx[2];
    	inline void update(){
    		minn[0] = min(ch[0]->minn[0],ch[1]->minn[0],pos[0]);
    		maxx[0] = max(ch[0]->maxx[0],ch[1]->maxx[0],pos[0]);
    		minn[1] = min(ch[0]->minn[1],ch[1]->minn[1],pos[1]);
    		maxx[1] = max(ch[0]->maxx[1],ch[1]->maxx[1],pos[1]);
    	}
    }*null,*root;
    Node T[maxn],asd;
    inline void init(){
    	null = &asd;null->ch[0] = null->ch[1] = null;
    	null->minn[0] = null->minn[1] = 0x3f3f3f3f;
    	null->maxx[0] = null->maxx[1] = -0x3f3f3f3f;
    }int nowd;
    inline bool cmp(const Node &a,const Node &b){
    	return a.pos[nowd] < b.pos[nowd];
    }
    Node *build(int l,int r,int s){
    	if(l > r) return null;
    	int mid = (l+r) >> 1;
    	nowd = s % dem;
    	nth_element(T+l,T+mid,T+r+1,cmp);
    	Node *p = &T[mid];
    	p->ch[0] = build(l,mid-1,s+1);
    	p->ch[1] = build(mid+1,r,s+1);
    	p->update();return p;
    }
    ll ans_max,ans_min;
    inline ll cat_abs(int x){return x < 0 ? -x : x;}
    Node op;
    inline ll get_max(Node *p){
    	ll ret = 0;
    	ret = max(ret,cat_abs(op.pos[0]-p->minn[0]) + cat_abs(op.pos[1]-p->minn[1]));
    	ret = max(ret,cat_abs(op.pos[0]-p->minn[0]) + cat_abs(op.pos[1]-p->maxx[1]));
    	ret = max(ret,cat_abs(op.pos[0]-p->maxx[0]) + cat_abs(op.pos[1]-p->minn[1]));
    	ret = max(ret,cat_abs(op.pos[0]-p->maxx[0]) + cat_abs(op.pos[1]-p->maxx[1]));
    	return ret;
    }
    inline ll get_min(Node *p){
    	ll ret = 0;
    	for(int d=0;d<dem;d++) if(op.pos[d]<p->minn[d]||op.pos[d]>p->maxx[d])
    		ret+=(op.pos[d]<p->minn[d])?p->minn[d]-op.pos[d]:op.pos[d]-p->maxx[d];
    	return ret;
    }
    void query_max(Node *p){
    	if(p == null) return;
    	ll dis = 0;
    	for(int d=0;d<dem;++d) dis += cat_abs(p->pos[d] - op.pos[d]);
    	if(p->id != op.id) ans_max = max(ans_max,dis);
    	if(get_max(p->ch[0]) < get_max(p->ch[1])) swap(p->ch[0],p->ch[1]);
    	if(get_max(p->ch[0]) > ans_max)  query_max(p->ch[0]);
    	if(get_max(p->ch[1]) > ans_max)  query_max(p->ch[1]);
    }
    void query_min(Node *p){
    	if(p == null) return;
    	ll dis = 0;
    	for(int d=0;d<dem;++d) dis += cat_abs(p->pos[d] - op.pos[d]);
    	if(p->id != op.id) ans_min = min(ans_min,dis);
    	if(get_min(p->ch[0]) > get_min(p->ch[1])) swap(p->ch[0],p->ch[1]);
    	if(get_min(p->ch[0]) < ans_min) query_min(p->ch[0]);
    	if(get_min(p->ch[1]) < ans_min) query_min(p->ch[1]);
    }
    int main(){
    	init();
    	int n;read(n);
    	for(int i=1;i<=n;++i){
    		read(T[i].pos[0]);
    		read(T[i].pos[1]);
    		T[i].id = i;T[i].ch[0] = T[i].ch[1] = null;
    		T[i].update();
    	}root = build(1,n,1);
    	ll ans = 1LL<<60;
    	for(int i=1;i<=n;++i){
    		op = T[i];
    		ans_max = 0;
    		ans_min = 1LL<<60;
    		query_min(root);
    		query_max(root);
    		ans = min(ans,ans_max - ans_min);
    	}printf("%lld
    ",ans);
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    long和Long的区别
    C语言的变量的内存分配
    Java蓝桥杯 算法提高 九宫格
    Java实现 蓝桥杯算法提高金明的预算方案
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6427216.html
Copyright © 2011-2022 走看看