描述
在一片廣袤無垠的原野上,散落著N塊磁石。每個磁石的性質可以用一個五元組(x,y,m,p,r)描述,其中x,y表示其座標,m是磁石的品質,p是磁力,r是吸引半徑。若磁石A與磁石B的距離不大於磁石A的吸引半徑,並且磁石B的品質不大於磁石A的磁力,那麼A可以吸引B。
小取酒帶著一塊自己的磁石L來到了這篇原野的(x0,y0)處,我們可以視為磁石L的座標為(x0,y0)。小取酒手持磁石L並保持原地不動,所有可以被L吸引的磁石將會被吸引過來。在每個時刻,他可以選擇更換任意一塊自己已經獲得的磁石(當然也可以是自己最初攜帶的L磁石)在(x0,y0)處吸引更多的磁石。小取酒想知道,他最多能獲得多少塊磁石呢。
輸入格式
第一行五個整數x0,y0,pL,rL,N,表示小取酒所在的位置,磁石L磁力、吸引半徑和原野上散落磁石的個數。
接下來N行每行五個整數x,y,m,p,r,描述一塊磁石的性質。 輸出格式
輸出一個整數,表示最多可以獲得的散落磁石個數(不包含最初攜帶的磁石L)。
把所有石頭按照品質排序分成sqrt(n)塊,每一塊裡面再按照距離排序。
用一塊石頭的時候,先找到所有品質全小於當前磁力的整塊,然後按順序拿走距離滿足要求的,多出來的那一塊暴力。
整個操作可以分成兩部分,取整塊的和取不完整的。對於整塊的,尋找需要O(sqrt(n))次,總共尋找O(n)次。每塊只會被取一次,總共O(n)次。多出來的一段,每次暴力O(sqrt(n))個,暴力O(n)次。所以總的複雜度O(n*sqrt(n))。
#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define LL long longusing namespace std;const double eps=1e-6;struct rock{ int m,p,r; double d;}a[250010];int rd(){ int x=0,f=1; char c=getchar(); while ((c<'0'||c>'9')&&c!='-') c=getchar(); if (c=='-') { f=-1; c=getchar(); } while (c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f;}bool cmpm(const rock &r1,const rock &r2){ return r1.m<r2.m;}bool cmpd(const rock &r1,const rock &r2){ return r1.d<r2.d;}bool out[250010];int L[510],R[510],maxm[510],to[510],n,tot,que[250010];int main(){ int i,j,k,m,n,p,q,x0,y0,hd,tl,ans=0; double x,y,z; x0=rd(); y0=rd(); a[0].p=rd(); a[0].r=rd(); n=rd(); for (i=1;i<=n;i++) { p=rd(); q=rd(); a[i].m=rd(); a[i].p=rd(); a[i].r=rd(); a[i].d=sqrt((LL)(p-x0)*(p-x0)+(LL)(q-y0)*(q-y0)+0.0); } sort(a+1,a+n+1,cmpm); tot=sqrt(n+0.1); for (i=1;i<=tot;i++) { L[i]=R[i-1]+1; to[i]=L[i]-1; R[i]= i==tot?n:L[i]+tot-1; maxm[i]=a[R[i]].m; } for (i=1;i<=tot;i++) sort(a+L[i],a+R[i]+1,cmpd); hd=tl=1; while (hd<=tl) { p=que[hd++]; for (i=1;i<=tot&&maxm[i]<=a[p].p;i++) { while (to[i]<R[i]&&a[to[i]+1].d<=eps+a[p].r) { to[i]++; if (!out[to[i]]) { que[++tl]=to[i]; ans++; out[to[i]]=1; } } } if (i<=tot) for (j=to[i]+1;j<=R[i];j++) if (out[j]==0&&a[j].d<=eps+a[p].r&&a[j].m<=a[p].p) { out[j]=1; ans++; que[++tl]=j; } } printf("%d\n",ans);}