CH #46A - 磁力块 - (分块)

2024-04-05 20:18
文章标签 ch 分块 磁力 46a

本文主要是介绍CH #46A - 磁力块 - (分块),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题面:

描述
在一片广袤无垠的原野上,散落着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。
对于100%的数据,1<=N<=250000,-10^9<=x,y<=10^9,1<=m,p,r<=10^9。

 

分析:

首先,假设手上有若干块磁铁,我要让我吸到的磁铁尽可能多,显然最简单的办法就是把手上的磁铁都拿来吸吸看,把能吸到的都吸过来,所以可以用类似于BFS的形式,对手头的磁铁用一个队列维护,取出队头磁铁尝试吸引,把能吸到的磁铁都入队,反复如此知道队列为空,即可知道已经吸到了所有能被吸过来的磁铁。

由于考虑一个磁铁能不能被吸引过来,要看满足两个条件与否:

  1、距离 ≤ 吸引半径

  2、手头磁铁的磁力 ≥ 被吸引的磁铁的质量

对平面上所有磁铁按照与我的距离从近到远进行升序排序,分成 T

块,显然每个分块内含有 O(NT)

个磁铁,再对每个分块内的磁铁按照质量升序排序,

那么,对于当前的查询 Q(p,r),对于吸引半径 r,必然存在一个整数 k,满足:

  1、第 1∼k个分块中所有磁铁距离均小于等于 r;

  2、第 k+2个分块中所有磁铁距离均大于 r,不可能被吸引;

分类讨论:

  ①对于满足距离条件的第 1∼k个分块,分别从每个块的块头开始遍历,直到某一个磁铁质量大于磁力 p时就停止,同时将该磁铁设为新的块头;

  ②对于不确定是否满足距离条件的第 k+1个分块,暴力枚举块内所有磁铁,判断是否能被吸引,能吸引的就取走即可。

时间复杂度:

  对于①,对于某一个分块,由于其中每个磁铁都只会被取走一次,均摊复杂度为 O(1)

,一次询问最多处理 O(T) 个分块,因此每次询问时间复杂度 O(T);

  对于②,每次询问需要 O(NT)的暴力枚举。

  ①和②合起来就是 O(T+NT),显然取 T=√ N时最小,为 O(√N);又最多有 O(N) 次询问,总时间复杂度 O(N√N)。

参考:https://www.cnblogs.com/dilthey/p/9789584.html。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 250006;
struct P {int x, y, m, p, r;
} p[N], q[N];
bool b[N];
int n, L[N], R[N], M[N];bool cmp(P a, P b) {return a.m < b.m;
}bool cmp0(P a, P b) {return (ll)(a.x - q[0].x) * (a.x - q[0].x) + (ll)(a.y - q[0].y) * (a.y - q[0].y) < (ll)(b.x - q[0].x) * (b.x - q[0].x) + (ll)(b.y - q[0].y) * (b.y - q[0].y);
}bool pd(P a, P b) {return (ll)(q[0].x - b.x) * (q[0].x - b.x) + (ll)(q[0].y - b.y) * (q[0].y - b.y) <= (ll)a.r * a.r;
}int main() {cin >> 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, cmp);/// 按质量排序int t = sqrt(n); /// 块的大小/// 预处理每一块的左右端点和最大质量for (int i = 1; i <= t; i++) {L[i] = (i - 1) * t + 1;R[i] = i * t;M[i] = p[R[i]].m;sort(p + L[i], p + R[i] + 1, cmp0);/// 内部按距离排序}/// 末尾if (R[t] < n) {L[t+1] = R[t] + 1;R[++t] = n;M[t] = p[R[t]].m;sort(p + L[t], p + R[t] + 1, cmp0);}/// BFS框架int l = 0, r = 1;memset(b, 0, sizeof(b)); /// 搜索队列while (l < r) {int k = 0;for (int i = 1; i <= t; i++)if (M[i] <= q[l].p) k = i;else break;/// 第 1-k 个分块中所有磁铁距离均小于等于 rfor (int i = 1; i <= k; i++)while (L[i] <= R[i] && pd(q[l], p[L[i]])) {if (!b[L[i]]) {b[L[i]] = 1;q[r++] = p[L[i]];}++L[i];}/// 分别从每个块的块头开始遍历,直到某一个磁铁质量大于磁力 p 时就停止,同时将该磁铁设为新的块头if (t != k++)for (int i = L[k]; i <= R[k]; i++)if (!b[i] && p[i].m <= q[l].p && pd(q[l], p[i])) {b[i] = 1;q[r++] = p[i];}/// 尾巴(残余块处理)++l;}cout << r - 1 << endl;return 0;
}

 

这篇关于CH #46A - 磁力块 - (分块)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/878046

相关文章

Spring Boot实现大文件分块上传

1.分块上传使用场景 大文件加速上传:当文件大小超过100MB时,使用分片上传可实现并行上传多个Part以加快上传速度。 网络环境较差:网络环境较差时,建议使用分片上传。当出现上传失败的时候,您仅需重传失败的Part。 文件大小不确定: 可以在需要上传的文件大小还不确定的情况下开始上传,这种场景在视频监控等行业应用中比较常见。 2.实现原理 实现原理其实很简单,核心就是客户端把大文件

【BNU】40719 Arithmetic Progressions【分块+FFT】

传送门:【BNU】40719 Arithmetic Progressions 题目分析: 用分块+FFT强行AC了这题…… 之前一直TLE……然后改了好久把姿势改的优美点了……终于过了…… 大概思路是:我们考虑分块,假设每一块的大小为S,一共分了B块然后我们分两种情况讨论: 1.第二个数在第i块,第一个数在(1~i-1)块内,第三个数在(i+1~B)块内。 2.至少两个数在同一块内。

【HDU】5213 Lucky 【分块(在线算法)】

传送门:【HDU】5213 Lucky 题目分析: 我来说一下这题的在线做法。 首先我们将区间分成 n√ \sqrt n块,用f[x][y]表示第x块的数和第y块的数相加等于K的对数,这个可以 O(nn√) O(n \sqrt n)的预处理。然后还有g[x][y]表示在第1~x块中有的大小为y的数的个数,这个的复杂度同样 O(nn√) O(n \sqrt n)。 接下来,对于每组询问,我们

针对大数据的种子点生长——分块生长的策略

前言   在之前的种子点生长系列中,探讨了使用三种提取图像中内容部分种子点生长算法,分别是泛洪法、扫描线法和区段法。我们知道这三种算法在空间上都需要占用三维图像的空间以及相应的位图标记表的空间。有时,我们需要处理一些体积相当大的数据,这些数据都是内存中无法放下的,如数十数百GB的数据,想要获得其中图像内容信息,一般需要对图像进行分块生长。   本文使用一种比较直接的思路对数据进行分块,然

P3313 [SDOI2014] 旅行(分块做法)

~~~~~      P3313 [SDOI2014] 旅行 ~~~~~      总题单链接 思路 ~~~~~      遇到这种树上路径问题,就考虑用重链剖分转为区间问题。 ~~~~~      问题转换为了:给定一个区间和 k k k,求这个区间内信仰为 k k k 的城市的 权值和 或 最大权值。 ~~~~~      这个问题也可以用动态开点线段树解决(现在不会,以后

【C++二分查找 贪心】1552. 两球之间的磁力

本文涉及的基础知识点 C++二分查找 贪心:决策兼容性 LeetCode1552. 两球之间的磁力 在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子,第 i 个篮子的位置在 position[i] ,Morty 想把 m 个球放到这些篮子里,使得任意两球间 最小磁力 最大。 已知两个球如果分别位于 x

学习笔记 ---- 数论分块(整除分块)

文章目录 算法概述引理引理 1 1 1引理 2 2 2 数论分块结论(区间右端点公式)过程 N N N 维数论分块向上取整的数论分块 例题 H ( n ) H(n) H(n)[CQOI2007] 余数求和[清华集训2012] 模积和 算法 概述 数论分块可以快速计算一些含有除法向下取整的和式(即形如 ∑ i = 1 n f ( i ) g ( ⌊ n i ⌋ ) \sum

C/C++网络编程--文件分块传输

文件分块传输是网络编程中一个常见的任务,尤其是在处理大文件时,将文件分块可以提高传输效率,简化错误处理,并可以实现并发传输。下面,写个从客户端向服务器发送大型数据的demo。 客户端 客户端有两点需要注意,在传输分两个一个是文件总块数和文件块,。传输文件总块数让服务器知道有多少文件块需要接收,确保所有数据都被完整地发送到服务器,避免因文件块数不对导致文件重组失败。 传输文件总块数 int

BT磁力下载器

下载 用法 usage: BTDown [OPTIONS] [TORRENT|MAGNETURL]OPTIONS:CLIENT OPTIONS-h print this message-f <log file> logs all events to the given file-s <path> sets the

初学HTML用法大全指导(五)html建立网页中的表单与DIV、SPAN分块

上一篇博客我们讲了html脚本语言中超链接的创建与使用,这一篇博客我们来聊一聊web网页中常用的表单的建立,我们在登录一个新的网站时想成为这个网站的VIP会员或者普通用户时常常面临着各种信息的登记,以及在登录这个系统时要输入自己的账户和密码,比如CSDN中,我们想登录进入自己的账户时,就要输入账户和密码。这是HTML脚本语言中的表单操作就称为了很重要的作用。最常见的表单标签有:文本框