1. 程式人生 > >CH Round #46A 磁力塊

CH Round #46A 磁力塊

++ print memset line cor ble 是否 i++ nod

還是一道好題的

對於一個磁石是否被吸引,有兩個關鍵字:距離和質量。(二維偏序??)

好像是很厲害的分塊姿勢,先按第一關鍵字排序,在塊中按第二關鍵字排

進行bfs,對於當前磁石,有1~k-1個塊是第一關鍵字全部小於等於當前磁石的,那麽暴力從塊首往後,找到第一個第二關鍵字大於當前磁石屬性的,那麽前面都撿走,以後可以從這裏開始找。

暴力枚舉第k個塊找答案。

一個優化就是找k的時候直接比較當前塊的最大值就行了,因為當前的屬性肯定是>kmin,<kmax滴

(垃圾CH本機AC提交WA幸好最後我搞對了)

#include<cstdio>
#include<iostream>
#include
<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; int n; struct node{LL dis,m,p,r;}a[310000];bool v[310000]; bool cmp1(node n1,node n2){return n1.m<n2.m;} bool cmp2(node n1,node n2){return n1.dis<n2.dis;} int
block,st[310000]; struct LIST { LL p,r; }list[310000]; int be[610];LL mx[610]; int findk(LL p) { for(int i=1;i<=block;i++) if(p<mx[i])return i; return block+1; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); LL xx,yy,x,y; scanf(
"%lld%lld%lld%lld%d",&xx,&yy,&list[1].p,&list[1].r,&n); for(int i=1;i<=n;i++) { scanf("%lld%lld%lld%lld%lld",&x,&y,&a[i].m,&a[i].p,&a[i].r); a[i].dis=(x-xx)*(x-xx)+(y-yy)*(y-yy); } sort(a+1,a+n+1,cmp1); block=(int(sqrt(double(n+1))))+1; for(int i=1;i<=n;i++)st[i]=(i-1)/block+1; for(int i=1;i<=block;i++) { int St=(i-1)*block+1,Ed=min(i*block,n);mx[i]=a[Ed].m; if(St<=Ed)sort(a+St,a+Ed+1,cmp2); } for(int i=1;i<=block;i++)be[i]=1; memset(v,false,sizeof(v)); int head=1,tail=2,ans=0; while(head<tail) { LL p=list[head].p,r=list[head].r; int k=findk(p); for(int i=1;i<=k-1;i++) { for(int j=be[i];j<=block&&(i-1)*block+j<=n;j++) { int u=(i-1)*block+j; if(a[u].dis>r*r){be[i]=j;break;} { if(v[u]==false) { v[u]=true; ans++; list[tail].p=a[u].p, list[tail].r=a[u].r; tail++; } } } } if(k!=block+1) { for(int j=be[k];j<=block&&(k-1)*block+j<=n;j++) { int u=(k-1)*block+j; if(a[u].dis>r*r)break; else if(a[u].m<=p) { if(v[u]==false) { v[u]=true; ans++; list[tail].p=a[u].p, list[tail].r=a[u].r; tail++; } } } } head++; } printf("%d\n",ans); return 0; }

CH Round #46A 磁力塊