• 《算法竞赛进阶指南》0x44分块 AcWing磁力块


    题目链接:https://www.acwing.com/problem/content/252/

    题目给出一些点的坐标,质量,磁力和吸引半径,初始时刻只有一个磁石在(x0,y0)位置,可以通过磁石吸引其他磁石,然后选择磁石继续进行吸引,问最终可以得到多少磁石?

    由于磁石的吸引要满足距离小于吸引半径,质量小于等于其磁力,所以可以按照质量进行排序分块,第二个约束在分块內进行排序,保存分块的最大的质量。对于可以拿的磁石都放入队列,进行BFS,完全小于其质量的只要从每段的头部开始取就可以,每段的头部在取完之后要变动到最终不可取的位置。而质量不完全小于等于队首元素的磁力的时候就需要对每个磁石单独进行判断。在对完全满足的进行判断的时候,是否访问过的判断要在while循环中,要保证L[i]在满足两个条件的情况下必须后移。还要注意平方的时候都要变成ll进行判断,否则会wa。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 250010;
    const int T = 550;
    struct node{
        int x,y,m,p,r;
    }p[maxn],q[maxn];
    int n;
    int L[maxn],R[maxn],M[maxn];
    bool vis[maxn];
    inline bool cmp0(node& a,node& b){
        return a.m<b.m;
    }
    inline ll dis2(node& a){
        return (ll)(a.x-q[0].x)*(a.x-q[0].x)+(ll)(a.y-q[0].y)*(a.y-q[0].y);
    }
    inline bool cmp1(node& a,node& b){
        return dis2(a)<dis2(b);
    }
    int main(){
        scanf("%d%d%d%d%d",&q[0].x,&q[0].y,&q[0].p,&q[0].r,&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d%d%d",&p[i].x,&p[i].y,&p[i].m,&p[i].p,&p[i].r);
        
        sort(p+1,p+n+1,cmp0);//按照质量进行排序
        int t=sqrt(n);
        int len=t?n/t:n;
        for(int i=1;i<=t;i++){
            L[i]=(i-1)*len+1;
            R[i]=i*len;
            M[i]=p[R[i]].m;//分块内部的最大质量 
            sort(p+L[i],p+R[i]+1,cmp1);//按照距离进行组内的二次排序 
        } 
        if(R[t]<n){
            L[t+1]=R[t]+1;
            R[++t]=n;
            M[t]=p[n].m;
            sort(p+L[t],p+R[t]+1,cmp1);
        }
        int ans=0; 
        int l=0,r=1;
        while(l<r){
            int k=0;
            for(int i=1;i<=t;i++){//找到最后一个块k,前面的都是<=队头磁石的质量的 
                if(M[i]<=q[l].p)k=i;
                else break;
            }
            for(int i=1;i<=k;i++){ 
                while(L[i]<=R[i] && dis2(p[L[i]])<=(ll)q[l].r*q[l].r){
                    if(!vis[L[i]]){//在单独处理的块块中被访问 
                        vis[L[i]]=1;//同一个磁石不会算两次 
                        ans++;
                        q[r++]=p[L[i]];
                    }
                    L[i]++;
                }
            }
            if(t!=k){//不是最后一个块 
                k++;//单独扫描当前块中的每个元素 
                for(int i=L[k];i<=R[k];i++){
                    if(!vis[i] && p[i].m<=q[l].p && dis2(p[i])<=(ll)q[l].r*q[l].r){
                        vis[i]=1;
                        ans++;
                        q[r++]=p[i];
                    }
                }
            }
            l++;
        }
        cout<<ans<<endl;
        return 0;
    } 
    每一个不曾起舞的日子,都是对生命的辜负。
  • 相关阅读:
    [摘抄]数据湖,大数据的下一个变革
    linux localhost 借助nginx 支持https
    mac os 下 android studio 选择模拟器设备的时候一直显示Loading
    SpringBoot 项目遇到错误: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    nexus-2.12.0-01 shiro漏洞升级
    IDEA 历史版本下载地址
    Postfix 554 5.7.1 Relay Access Denied
    Java SPI 机制实现项目框架高扩展性
    IDEA控制台 springboot输出中文乱码
    Setup Apache2 in Debian 9 and enable two ports for two sites
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13356376.html
Copyright © 2020-2023  润新知