bzoj2716 天使玩偶

傳送門
用之前的那種估值函數過不去。。
要記錄每個點所包含的最大範圍才過得去,每次查就看查詢點與這個範圍的最小可能距離。搜的時候先搜估值距離小的。
如果插入的點超過一定數量就重構一下,防止過於不平衡,不過貌似並沒有什麼卵用。

#include<bits/stdc++.h>
#define cs const
#define re register
#define lc(x) T[x].son[0]
#define rc(x) T[x].son[1]
cs int maxD=2,N=1e6+10,oo=1e9,rebuild=3e5;
int n,m,t,ans,x,y,INS=0;
namespace IO{
	cs int Rlen=1<<22|1;
	char buf[Rlen],*p1,*p2;
	inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
	template<typename T>
	inline T get(){
		char ch;T x;
		while(!isdigit(ch=gc()));x=ch^48;
		while(isdigit(ch=gc())) x=((x+(x<<2))<<1)+(ch^48);
		return x;
	}
	inline int gi(){return get<int>();}
}
using IO::gi;
using std::max;
inline void Min(int &x,int y){if(x>y)x=y;}
inline void Max(int &x,int y){if(x<y)x=y;}
namespace KD_tree{
	#define mid (l+r>>1)
	int tot=0,cmp_d,root=0;
	struct node{
		int mx[maxD],mn[maxD],val[maxD],son[2];
		node(int X=0,int Y=0){
			mx[0]=mn[0]=val[0]=X;
			mx[1]=mn[1]=val[1]=Y;
			son[0]=son[1]=0;
		}
	}T[N];
	inline bool cmp(cs node &a,cs node &b){return a.val[cmp_d]<b.val[cmp_d];}
	inline void pushup(int root){
		if(lc(root)){
			Min(T[root].mn[0],T[lc(root)].mn[0]),Max(T[root].mx[0],T[lc(root)].mx[0]);
			Min(T[root].mn[1],T[lc(root)].mn[1]),Max(T[root].mx[1],T[lc(root)].mx[1]);
		}
		if(rc(root)){
			Min(T[root].mn[0],T[rc(root)].mn[0]),Max(T[root].mx[0],T[rc(root)].mx[0]);
			Min(T[root].mn[1],T[rc(root)].mn[1]),Max(T[root].mx[1],T[rc(root)].mx[1]);
		}
	}
	inline int build(int l,int r,int div){
		if(l>r) return 0;cmp_d=div;
		std::nth_element(T+l,T+mid,T+r+1,cmp);
		int u=mid;
		T[u].son[0]=build(l,mid-1,div^1);
		T[u].son[1]=build(mid+1,r,div^1);
		return pushup(mid),mid;
	}
	inline void ins(int &now,int x,int y,int div){
		if(!now) return void(T[now=++tot]=node(x,y));
		int w=div?y:x;
		if(w<T[now].val[div]) ins(T[now].son[0],x,y,div^1);
		else ins(T[now].son[1],x,y,div^1);
		pushup(now);
	}
	inline void insert(int x,int y){ins(root,x,y,0);}
	inline int dis(cs node &A,int x,int y,int ret=0){
		return max(0,A.mn[0]-x)+max(0,A.mn[1]-y)+max(0,x-A.mx[0])+max(0,y-A.mx[1]);
	}
	inline void ask(int pos,int x,int y){
		if(!pos) return;
		int dl=oo,dr=oo,curdis=abs(T[pos].val[0]-x)+abs(T[pos].val[1]-y);
		Min(ans,curdis);
		if(lc(pos)) dl=dis(T[lc(pos)],x,y);
		if(rc(pos)) dr=dis(T[rc(pos)],x,y);
		if(dl<dr){
			if(dl<ans) ask(lc(pos),x,y);
			if(dr<ans) ask(rc(pos),x,y);
		}
		else{
			if(dr<ans) ask(rc(pos),x,y);
			if(dl<ans) ask(lc(pos),x,y);
		}
	}
	#undef mid
}
using namespace KD_tree;
int main(){
//	freopen("3059.in","r",stdin);
	n=gi(),m=gi();
	for(int i=1;i<=n;++i) x=gi(),y=gi(),T[i]=node(x,y);
	root=build(1,n,0),KD_tree::tot=n;
	while(m--){
		t=gi();
		if(t==1){
			x=gi(),y=gi(),insert(x,y);
			if(++INS==rebuild) root=build(1,tot,0),INS=0;
		}
		if(t==2) ans=oo,x=gi(),y=gi(),ask(root,x,y),printf("%d\n",ans);
	}
}
發佈了192 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章