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;
    }
    
  • 相关阅读:
    谈谈final, finally, finalize的区别。
    session是存储在什么地方,以什么形式存储的
    如果有几千个session,怎么提高效率
    堆和栈的区别?
    进程和线程的区别?
    Delphi中启动项管理 已安装程序卸载简单组件
    在使用TStringlist谨慎使用For循环
    Delphi 中窗体全屏组件
    TEdit扩展:做成多按钮的Edit,可用作浏览器地址栏
    Delphi 7中处理TEdit鼠标进入 离开事件
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6427216.html
Copyright © 2011-2022 走看看