磁力塊


題目描述

在一片廣袤無垠的原野上,散落着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)

樣例輸入

0 0 5 10 5
5 4 7 11 5
-7 1 4 7 8
0 2 13 5 6
2 -3 9 3 4
13 5 1 9 9

樣例輸出

3

提示

對於30%的數據,1<=N<=1000。
對於另外30%的數據,p=r。
對於100%的數據,1<=N<=250000,-10^9<=x,y<=10^9,1<=m,p,r<=10^9。

BFS,把手里的磁石放進隊列中,每次將隊首元素能吸引的加進來
問題就是快速判斷哪些磁石能被吸引
能被吸引的磁石需要滿足 m<=p, dis<=r 
先把所有磁石按照質量排序,然后分塊,每塊內按照距離重新排序
那么對當前磁石來說,肯定存在一個k,前1~k段每塊磁石質量都比該塊磁石的磁力小,k+1段之后每塊磁石質量都比它大
對於1~k段,因為每塊內都按照距離排序了,因此能被吸引的一定是位於該段開頭部分,我們從前往后掃描,掃到不能吸引為止,然后更新區間左端點
對於第k段,暴力掃描,把能吸引的加進來即可
復雜度o(n√n)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
const int block=500;
int n,m,cnt;
double x,y,xx,yy;
int L[block],R[block],M[block];
bool vis[N];
struct orz{
    int p,r;};
queue<orz>q;
struct stu{
    int p,r,m;
    double dis;}a[N];
double dist(double x,double y)
{
    return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
bool cmp1(stu a,stu b)
{
    return a.m<b.m;
}
bool cmp2(stu a,stu b)
{
    return a.dis<b.dis;
}
int main()
{
    int p,r,n;
    scanf("%lf%lf%d%d%d",&xx,&yy,&p,&r,&n);

    for (int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&x,&y);
        a[i].dis=dist(x,y);
        scanf("%d%d%d",&a[i].m,&a[i].p,&a[i].r);
    }
    sort(a+1,a+1+n,cmp1);

    for (int i=1;i<=n;i+=block)
    {
        L[++cnt]=i;R[cnt]=min(cnt*block,n);
        M[cnt]=a[R[cnt]].m;
        sort(a+i,a+R[cnt]+1,cmp2);
    }

    int ans=0;
    q.push({p,r});
    while (!q.empty())
    {
        orz now=q.front();
        q.pop();

        for (int i=1;i<=cnt;i++)
        {
            if (M[i]>now.p)
            {
                for (int j=L[i];j<=R[i];j++)
                if (a[j].m<=now.p && a[j].dis<now.r && !vis[j])
                {
                    vis[j]=1;
                    ans++;
                    q.push({a[j].p,a[j].r});
                }
                break;
            }

            while (L[i]<=R[i] && a[L[i]].dis<=now.r)
            {
                if (!vis[L[i]])
                {
                    vis[L[i]]=1;
                    ans++;
                    q.push({a[L[i]].p,a[L[i]].r});
                }
                L[i]++;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM