P10590 磁力块

有一个很显然的 BFS,对于每一个吸到的新磁力块,遍历序列,把所有它能吸到的磁力块加入一个队列进行扩展。这样时间复杂度是 \(O(n^2)\),不能通过。

考虑影响是否能吸到的两个因素,一个是利用 \(x,y\) 计算出的距离,另一个是质量 \(m\)。对于这种问题,经典的做法是排序维护第一个变量,数据结构维护第二个变量。

由于本题需要取出可以吸到的磁力块入队,故 \(\log\) 数据结构在本题中不好用。我们考虑分块。把所有磁力块按照距离升序排序,每 \(\sqrt{n}\) 个元素分成一块。块内按照 \(m\) 升序排序,并记录距离的最大值。

当我们扩展一个磁力块时,从小到大遍历序列中的每一块。

对于一个最大距离小于等于吸引半径的块,所有磁力块均处于吸引半径之内。可以对于每一块记录一个 \(la\),表示块中已经前 \(la-1\) 个磁力块已经被吸引。我们只需要利用 \(la\),遍历到第 \(x\) 个元素,使这个元素的 \(m\) 大于当前吸力即可。由于 \(m\) 升序排序,所以这一块中所有可以被吸走的磁力块要么在之前被吸走,要么在这一次被吸走,满足条件。之后,令 \(la=x\)。

对于第一个最大距离大于吸引半径的块,根据遍历顺序以及距离升序排序,之后的块中所有元素距离必然大于吸引半径,可以处理完这一块之后退出循环。这一块之中有的磁力块可以被吸走,有的磁力块不可以被吸走。我们暴力求出每一个能够吸走的磁力块,标记已经被吸走,之后排序重构。均衡复杂度之后为 \(O(n\sqrt{n\log n})\),可以通过

事实上,可以继续优化。在处理第一个最大距离大于吸引半径的块时,我们不进行排序重构。改为在处理最大距离小于等于吸引半径的块时,如果遇到一个被吸走的磁力块,直接跳过到下一个。由于 \(m\) 升序排序,依旧满足要求。时间复杂度 \(O(n\sqrt{n})\)。

#include <bits/stdc++.h>
using namespace std;
struct val
{
long long m,p,r;
double d;
}a[300000];
long long xq,yq,x,y,p,r,n,k,qp[300000],qr[300000],h=1,t=0,id[300000],la[300000],lc[300000],rc[300000],ans=-1;
double mx[300000];
bool cmp1(struct val a,struct val b)
{
return a.d<b.d;
} bool cmp2(struct val a,struct val b)
{
return a.m<b.m;
} double dist(long long x1,long long y1,long long x2,long long y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
} void expand(long long p,long long r)
{
for(int i=1;i<=(n+k-1)/k;i++)
if(mx[i]<=r)
while(a[la[i]].m<=p&&la[i]<=rc[i])
{
if(a[la[i]].m!=-1e10)qp[++t]=a[la[i]].p,qr[t]=a[la[i]].r,a[la[i]].m=-1e10;
la[i]++;
}
else
{
la[i]=lc[i];
for(int j=lc[i];j<=rc[i];j++)
if(a[j].m!=-1e10&&a[j].m<=p&&a[j].d<=r)qp[++t]=a[j].p,qr[t]=a[j].r,a[j].m=-1e10;
break;
}
} int main()
{
scanf("%lld%lld%lld%lld%lld",&xq,&yq,&p,&r,&n);
qp[++t]=p,qr[t]=r,k=sqrt(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].d=dist(xq,yq,x,y);
}
sort(a+1,a+n+1,cmp1);
for(int i=1;i<=(n+k-1)/k;i++)lc[i]=1e10;
for(long long i=1;i<=n;i++)id[i]=(i-1)/k+1,lc[id[i]]=min(lc[id[i]],i),rc[id[i]]=max(rc[id[i]],i),mx[id[i]]=max(mx[id[i]],a[i].d);
for(int i=1;i<=(n+k-1)/k;i++)la[i]=lc[i],sort(a+lc[i],a+rc[i]+1,cmp2);
while(h<=t)ans++,expand(qp[h],qr[h]),h++;
printf("%lld\n",ans);
return 0;
}

Luogu P10590 磁力块的更多相关文章

  1. CH#46A 磁力块

    题意 磁力块 CH Round #46 - 「Adera 8」杯NOI模拟赛 描述 在一片广袤无垠的原野上,散落着N块磁石.每个磁石的性质可以用一个五元组(x,y,m,p,r)描述,其中x,y表示其坐 ...

  2. 『磁力块 bfs 分块』

    磁力块 Description 在一片广袤无垠的原野上,散落着N 块磁石.每个磁石的性质可以用一个五元组 (x,y,m,p,r)描述,其中x,y 表示其坐标,m 是磁石的质量,p 是磁力,r 是吸引半 ...

  3. 【CHOJ】磁力块

    题意描述 磁力块 在平面内分布着 \(N\) 个磁力块,同时你的手上也有一块. 你一开始站在给定的坐标上,当磁力块之间满足互相吸引的条件时就可以吸引. 当你拿到新的磁石时你就可以用它来吸引更多的石头, ...

  4. CH#46 磁力块 分块

    正解:分块+bfs 解题报告: 先放个传送门,然后瞎扯淡下QAQ 突然感觉不停课大概是正确的选择QAQ 大概实在是没有天赋?明明都知道正解是分块甚至还听了下解法感觉理解了,再看一次依然没想到解法,,, ...

  5. CH #46A - 磁力块 - [分块]

    题目链接:传送门 描述在一片广袤无垠的原野上,散落着N块磁石.每个磁石的性质可以用一个五元组(x,y,m,p,r)描述,其中x,y表示其坐标,m是磁石的质量,p是磁力,r是吸引半径.若磁石A与磁石B的 ...

  6. Contest Hunter #46 T1 磁力块 [分块]

    描述 在一片广袤无垠的原野上,散落着N块磁石.每个磁石的性质可以用一个五元组(x,y,m,p,r)描述,其中x,y表示其坐标,m是磁石的质量,p是磁力,r是吸引半径.若磁石A与磁石B的距离不大于磁石A ...

  7. Contest Hunter #46 T1 磁力块 [花式暴力]

    将所有石头按距离远近排序,将所有取到的时候扔进堆里维护最大磁力强度. 贪心,每次用强度最强的磁石尝试吸引地上的石头,扫完区间以后,这块石头就再也不会用到了. 在此基础上可以做些小优化,比如说优化未取石 ...

  8. CH Round #46A 磁力块

    还是一道好题的 对于一个磁石是否被吸引,有两个关键字:距离和质量.(二维偏序??) 好像是很厉害的分块姿势,先按第一关键字排序,在块中按第二关键字排 进行bfs,对于当前磁石,有1~k-1个块是第一关 ...

  9. [洛谷Luogu]P1141 01迷宫[联通块 并查集]

    题目链接 大致题意 相邻格子不同为连通,计算每个点所在的连通块大小. 想法 我采用了并查集的做法. 开一个辅助数组记录连通块大小,每次合并的时候更新父亲节点的大小即可. 一个点先与它上面的点判定,若判 ...

  10. Luogu 2737 [USACO4.1]麦香牛块Beef McNuggets

    NOIP2017 D1T1 的结论,两个数$a, b$所不能表示出的最大的数为$a * b - a - b$. 听了好几遍证明我还是不会 注意到本题中给出的数都非常小,所以最大不能表示出的数$\leq ...

随机推荐

  1. MongoDB导出/导入操作

    1.从测试环境数据库导出数据 2.导入数据到本地数据库 mongoimport --host localhost --port 27017 --username root --password 123 ...

  2. iOS深色模式媒体查询css

    @media (prefers-color-scheme: dark) { body { background-color: #000; color: #fff; } }

  3. 被LangChain4j坑惨了!

    最近在深度体验和使用 Spring AI 和 LangChain4j,从开始的满怀期待五五开,但最后极具痛苦的使用 LangChain4j,让我真正体验到了正规军和草台班子的区别. Spring AI ...

  4. wpf 控件绑定鼠标命令、键盘命令

    1 <Window x:Class="CommandDemo.MainWindow" 2 xmlns="http://schemas.microsoft.com/w ...

  5. Graphpad Prism10.1.2 中文版科学绘图软件 安装包下载

    Prism10中文版下载链接: https://pan.baidu.com/s/18a0_uLi3ANWC3KxlHOzZAA?pwd=6666 提取码: 6666 Graphpad Prism 是一 ...

  6. 使用 chromedriver 实现网络爬虫【手抄】

    ​ 1.引用 selenium 包 <dependency> <groupId>org.seleniumhq.selenium</groupId> <arti ...

  7. 【经验】Git|Windows下如何管理和部署多个Git账号的SSH密钥文件

    生成 SSH 密钥 先打开一个git窗口,生成ssh密钥. 如果打开的不是git窗口,而是cmd窗口,则需要先切换到C:\Users\用户名\.ssh目录下. 下面这条指令的your_email和yo ...

  8. 内网私仓全流程搭建记录(二)-npm私仓提交与拉取

    1.npm私仓依赖下载及本地上传 方法一1)使用Pycharm创建py文档,写入如下py代码: import os import re import aiohttp import asyncio fr ...

  9. 详解SLAM中的李群和李代数(中)

    1 概述 在上一篇文章<详解SLAM中的李群和李代数(上)>中,我们已经通过对李群求导引出了李代数.在这篇文章中,我们就系统总结一下李代数的相关知识. 2 李代数 2.1 定义 李代数是一 ...

  10. 揭秘!测试开发速看,Mockaroo 如何轻松解决 90% 测试数据难题!

    在软件测试领域,模拟生成测试数据一直是至关重要的环节.无论是验证系统功能的准确性,还是测试边界条件下的系统稳定性,都离不开丰富且真实的测试数据. 今天,向大家推荐一款强大的模拟生成测试数据工具 --M ...