题目链接:传送门

描述
在一片广袤无垠的原野上,散落着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(\frac{N}{T})$ 个磁铁,再对每个分块内的磁铁按照质量升序排序,

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

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

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

分类讨论:

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

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

时间复杂度:

  对于①,对于某一个分块,由于其中每个磁铁都只会被取走一次,均摊复杂度为 $O(1)$,一次询问最多处理 $O(T)$ 个分块,因此每次询问时间复杂度 $O(T)$;

  对于②,每次询问需要 $O(\frac{N}{T})$ 的暴力枚举。

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

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=+;
const int maxt=+; struct Mg
{
ll x,y,m,p,r;
ll d;
}mg[maxn];
inline ll sqr(ll x){return x*x;}
inline ll dist(Mg a,Mg b){return sqr(a.x-b.x)+sqr(a.y-b.y);}
bool cmp1(Mg a,Mg b){return a.d<b.d;}
bool cmp2(Mg a,Mg b){return a.m<b.m;} int n;
int len,tot;
int L[maxt],R[maxt];
ll maxd[maxt];
int vis[maxn]; int main()
{
cin>>mg[].x>>mg[].y>>mg[].p>>mg[].r>>n;
mg[].r*=mg[].r;
for(int i=;i<=n;i++)
{
scanf("%lld%lld%lld%lld%lld",&mg[i].x,&mg[i].y,&mg[i].m,&mg[i].p,&mg[i].r);
mg[i].r*=mg[i].r;
mg[i].d=dist(mg[i],mg[]);
}
sort(mg+,mg+n+,cmp1); len=sqrt(n);
tot=;
for(int i=;i<=n;i+=len)
{
tot++;
L[tot]=i,R[tot]=min(i+len-,n);
maxd[tot]=mg[R[tot]].d;
sort(mg+L[tot],mg+R[tot]+,cmp2);
} int ans=;
memset(vis,,sizeof(vis));
queue<int> q;
q.push();
vis[]=;
while(!q.empty())
{
Mg &now=mg[q.front()]; q.pop(); ans++;
for(int i=;i<=tot;i++)
{
if(now.r>=maxd[i])
{
for(int &j=L[i];j<=R[i] && now.p>=mg[j].m;j++)
{
if(vis[j]) continue;
q.push(j);
vis[j]=;
}
}
else
{
for(int j=L[i];j<=R[i];j++)
{
if(vis[j]) continue;
if(now.r>=mg[j].d && now.p>=mg[j].m)
{
q.push(j);
vis[j]=;
}
}
break;
} }
} cout<<ans-<<endl;
}

CH #46A - 磁力块 - [分块]的更多相关文章

  1. CH#46A 磁力块

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

  2. CH#46 磁力块 分块

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

  3. CH Round #46A 磁力块

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

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

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

  5. 『磁力块 bfs 分块』

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

  6. 【CHOJ】磁力块

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

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

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

  8. HDU 4391 - Paint The Wall - 分块哈希入门

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=4391 题意 : 给一段区间, 有两种操作 1 : 给 x 到 y 的区间染色为 z 2 : 查询 ...

  9. (寒假开黑gym)2018 USP Try-outs

    layout: post title: (寒假开黑gym)2018 USP Try-outs author: "luowentaoaa" catalog: true tags: m ...

随机推荐

  1. java 字符串中参数化符号${}的解析

    我们在很多地方都能看到代表参数意义的符号${},可能我们在写一些框架的时候,有时候也需要用到这个符号,但他们是如何精确解析的?或者说需要我们自已写的时候,如何写?我们先来看以下的几个场景: 1.字符串 ...

  2. javascript中的数据结构

    Javascript中的关键字   abstract     continue      finally      instanceof      private       this boolean ...

  3. Java多线程并发最佳实践

    使用本地变量 尽量使用本地变量,而不是创建一个类或实例的变量. 使用不可变类 String.Integer等.不可变类可以降低代码中需要的同步数量. 最小化锁的作用域范围:S=1/(1-a+a/n) ...

  4. mac mini纯键盘操作连接蓝牙鼠标

    许久不开家里的MAC MINI了,今天开来玩玩,结果进个桌面连接鼠标就费了好大的劲 现实情况: 1. 没有有线鼠标,只有一个USB键盘,一个微软3600蓝牙鼠标 MAC MINI连接上USB键盘,开机 ...

  5. 译: 4. RabbitMQ Spring AMQP 之 Routing 路由

    在上一个教程中,我们构建了一个简单的fanout(扇出)交换.我们能够向许多接收者广播消息. 在本教程中,我们将为其添加一个功能 - 我们将只能订阅一部分消息.例如,我们将只能将消息指向感兴趣的特定颜 ...

  6. Android短信监听实现,及Android4.4之后短信机制变更

    前阵子公司有一个项目,简单的监听短信应用,功能只有如下两个: 1.监听短信并获取短信内容上传服务器: 2.从服务器获取短信内容,发送出去    按照传统的思路,监听短信我们有两种方式:第一种是使用广播 ...

  7. linux:rsync + inotifywait 实现【准实时】同步

    直接上脚本 #!/bin/bash export PATH=./sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:$PATH src=/tmp1 #dest=ro ...

  8. 汉字 Unicode 编码范围

    字符集 字数 Unicode 编码 基本汉字 20902字 4E00-9FA5 基本汉字补充 38字 9FA6-9FCB 扩展A 6582字 3400-4DB5 扩展B 42711字 20000-2A ...

  9. [Tensorflow] Object Detection API - prepare your training data

    From: TensorFlow Object Detection API This chapter help you to train your own model to identify obje ...

  10. ThinkingInJava 学习 之 0000002 操作符

    1. 更简单的打印语句 2. 使用Java操作符 3. 优先级(单目乘除位关系,逻辑三目后赋值) 4. 赋值 1. 方法调用中的别名问题 5. 算术操作符 6. 自动递增和递减 7. 关系操作符 1. ...