• 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
    ",ans);
      }
      return 0;
    }
    
    
  • 相关阅读:
    javascript 写一个随机范围整数的思路
    Promise中的next 另一个用法
    继上一篇随笔,优化3张以上图片轮播React组件
    低性能3张图片轮播React组件
    用函数式编程思维解析anagrams函数
    Python time time()方法
    torch.view().expand()
    pytorch中的top_K()函数
    设定学习率衰减
    两个集合求交集
  • 原文地址:https://www.cnblogs.com/Yuzao/p/9042904.html
Copyright © 2020-2023  润新知