BZOJ1665 : [Usaco2006 Open]The Climbing Wall 攀岩
直接BFS貌似复杂度飞起来了,于是我们用k-d tree优化找点的过程即可。时间复杂度$O(n\sqrt{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; }