BZOJ1665 : [Usaco2006 Open]The Climbing Wall 攀岩

直接BFS貌似复杂度飞起来了,于是我们用k-d tree优化找点的过程即可。时间复杂度$O(nsqrt{n})$。

#include<cstdio>
#include<algorithm>
const int N=10010,H=1000,R=1000000;
int n,m,i,root,cmp_d,h=1,t,q[N],f[N],mx,my,mz,ans;
inline void add(int x,int y){if(!f[x])f[q[++t]=x]=y;}
struct node{int d[2],l,r,Max[2],Min[2];}T[N];
inline bool cmp(node a,node b){
  return (a.d[cmp_d]<b.d[cmp_d])||((a.d[cmp_d]==b.d[cmp_d])&&(a.d[!cmp_d]<b.d[!cmp_d]));
}
inline void umax(int&a,int b){if(a<b)a=b;}
inline void umin(int&a,int b){if(a>b)a=b;}
inline void up(int x){
  if(T[x].l){
    umax(T[x].Max[0],T[T[x].l].Max[0]);
    umin(T[x].Min[0],T[T[x].l].Min[0]);
    umax(T[x].Max[1],T[T[x].l].Max[1]);
    umin(T[x].Min[1],T[T[x].l].Min[1]);
  }
  if(T[x].r){
    umax(T[x].Max[0],T[T[x].r].Max[0]);
    umin(T[x].Min[0],T[T[x].r].Min[0]);
    umax(T[x].Max[1],T[T[x].r].Max[1]);
    umin(T[x].Min[1],T[T[x].r].Min[1]);
  }
}
int build(int l,int r,int D){
  int mid=(l+r)>>1;
  cmp_d=D,std::nth_element(T+l+1,T+mid+1,T+r+1,cmp);
  T[mid].Max[0]=T[mid].Min[0]=T[mid].d[0];
  T[mid].Max[1]=T[mid].Min[1]=T[mid].d[1];
  if(l!=mid)T[mid].l=build(l,mid-1,!D);
  if(r!=mid)T[mid].r=build(mid+1,r,!D);
  return up(mid),mid;
}
inline int sqr(int x){return x*x;}
inline int max(int a,int b){return a>b?a:b;}
inline void ask(int x){
  if(!x)return;
  if(sqr(max(max(mx-T[x].Max[0],T[x].Min[0]-mx),0))+sqr(max(max(my-T[x].Max[1],T[x].Min[1]-my),0))>R)return;
  if(sqr(T[x].d[0]-mx)+sqr(T[x].d[1]-my)<=R)add(x,mz);
  ask(T[x].l);ask(T[x].r);
}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
  for(read(m),read(n),i=1;i<=n;i++)read(T[i].d[0]),read(T[i].d[1]);
  root=build(1,n,0);
  for(i=1;i<=n;i++)if(T[i].d[1]<=H)add(i,1);
  while(h<=t)mx=T[i=q[h++]].d[0],my=T[i].d[1],mz=f[i]+1,ask(root);
  for(ans=n,i=1;i<=n;i++)if(f[i]&&T[i].d[1]+H>=m&&ans>f[i])ans=f[i];
  return printf("%d",ans),0;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/4588474.html