bzoj 2648: SJY摆棋子

Description

这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。

Solution

\(kdtree\)
比普通的 \(kdtree\) 差不多,多了一个插入操作,像平衡树一样插入就行了
这样可能会复杂度退化,可以使用定期重构的方法来稳定复杂度
实测加上定期重构之后反而变慢了,此题数据范围不宜这么做

#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
	int f;char c;
	for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
	for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=1e6+10,inf=1e9;
int n,D,Q,B,rt,cnt,ans,op;
struct data{
	int a[2],mn[2],mx[2],l,r;
	inline int& operator [](int x){return a[x];}
}t[N],e;
inline bool operator <(data p,data q){return p[D]<q[D];}
inline void upd(int o){
	int ls=t[o].l,rs=t[o].r;
	for(int i=0;i<2;i++){
		t[o].mx[i]=max(t[o].mx[i],max(t[ls].mx[i],t[rs].mx[i]));
		t[o].mn[i]=min(t[o].mn[i],min(t[ls].mn[i],t[rs].mn[i]));
	}
}
inline int build(int l,int r,int k){
	D=k;
	int mid=(l+r)>>1,o=mid;
	nth_element(t+l,t+mid,t+r+1);
	for(int i=0;i<2;i++)t[o].mx[i]=t[o].mn[i]=t[o][i];
	if(l<mid)t[o].l=build(l,mid-1,k^1);
	if(r>mid)t[o].r=build(mid+1,r,k^1);
	return upd(o),o;
}
inline int ins(int o,int k){
	if(!o)return cnt;
	if(e[k]>t[o][k])t[o].r=ins(t[o].r,k^1);
	else t[o].l=ins(t[o].l,k^1);
	return upd(o),o;
}
inline int dis(int o){return abs(t[o][0]-e[0])+abs(t[o][1]-e[1]);}
inline int cmin(int o){
	if(!o)return 0;
	int ret=0;
	for(int i=0;i<2;i++)ret+=max(0,e[i]-t[o].mx[i])+max(0,t[o].mn[i]-e[i]);
	return ret;
}
inline void qmin(int o){
	if(!o)return ;
	int dl=cmin(t[o].l),dr=cmin(t[o].r),dc=dis(o);
	ans=min(ans,dc);
	if(dl<dr){
		if(dl<ans)qmin(t[o].l);
		if(dr<ans)qmin(t[o].r);
	}
	else{
		if(dr<ans)qmin(t[o].r);
		if(dl<ans)qmin(t[o].l);
	}
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  cin>>n>>Q;B=sqrt(n+Q);cnt=n;
  for(int i=1;i<=n;i++)gi(t[i][0]),gi(t[i][1]);
  for(int i=0;i<=1;i++)t[0].mx[i]=-inf,t[0].mn[i]=inf;
  rt=build(1,n,0);
  while(Q--){
	  gi(op);gi(e[0]);gi(e[1]);
	  if(op==1){
		  t[++cnt]=e;
		  for(int i=0;i<2;i++)t[cnt].mx[i]=t[cnt].mn[i]=e[i];
		  rt=ins(rt,0);
	  }
	  else ans=inf,qmin(rt),printf("%d\n",ans);
  }
  return 0;
}

posted @ 2018-07-15 11:53  PIPIBoss  阅读(250)  评论(0编辑  收藏  举报