题目:CH#46A.
题目大意:有一个元素
a
0
=
(
x
0
,
y
0
,
m
0
,
p
0
,
r
0
)
a_0=(x_0,y_0,m_0,p_0,r_0)
a0=(x0,y0,m0,p0,r0)和其它
n
n
n个元素
a
i
=
(
x
i
,
y
i
,
m
i
,
p
i
,
r
i
)
a_i=(x_i,y_i,m_i,p_i,r_i)
ai=(xi,yi,mi,pi,ri).现在维护一个集合初始只有元素
a
0
a_0
a0,然后对于集合中每一个元素
a
i
a_i
ai可以把所有满足条件的
a
j
a_j
aj取入集合.问集合稳定后的元素个数
−
1
-1
−1.
条件为:
(
x
0
−
x
j
)
2
+
(
y
0
−
y
j
)
2
≤
r
i
m
j
≤
p
i
\sqrt{(x_0-x_j)^2+(y_0-y_j)^2}\leq r_i\\ m_j\leq p_i
(x0−xj)2+(y0−yj)2≤rimj≤pi
1 ≤ n ≤ 2.5 ∗ 1 0 5 1\leq n\leq 2.5*10^5 1≤n≤2.5∗105.
这道题的运行过程完全就是bfs的板子,所以直接用bfs来模拟即可把问题转化为一个元素会让哪些元素加入集合.
为了解决这个问题,我们先把所有元素按照 m m m排序,现在我们会发现所有满足 m j < p i m_j<p_i mj<pi的元素 j j j一定在一个左端点为1的区间内了.
那么如何找出这之中那些满足第一个条件的元素并删除呢?我们在把这个排好序的序列分块,每一块的内部再按照 ( x 0 − x j ) 2 + ( y 0 − y j ) 2 (x_0-x_j)^2+(y_0-y_j)^2 (x0−xj)2+(y0−yj)2排序,然后每次查询整块的时候从开头开始删除(肯定是包含块开头连续的一段会被删除),不在整块内则暴力删除,这样做可以保证总时间复杂度为 O ( n n ) O(n\sqrt{n}) O(nn)…
这道题貌似就是BZOJ3276,但是分块做法会TLE,需要线段树,等我哪天有时间了再搞搞吧其实就是鸽了.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=250000,G=500;
LL sqr(LL a){return a*a;}
int sx,sy,x,y,n;
struct node{
int m,p;
LL l,r;
}a[N+9];
bool cmp1(const node &a,const node &b){return a.m<b.m;}
bool cmp2(const node &a,const node &b){return a.l<b.l;}
struct block{
int l,r,ca,now;
node a[G+9];
}bl[G+9];
int cb,siz,bel[N+9],ans;
void Build(int n){
siz=500;
while (bl[cb].r<n){
++cb;
bl[cb].l=bl[cb-1].r+1;bl[cb].r=min(bl[cb].l+siz-1,n);
for (int i=bl[cb].l;i<=bl[cb].r;++i){
bel[i]=cb;
bl[cb].a[++bl[cb].ca]=a[i];
}
sort(bl[cb].a+1,bl[cb].a+1+bl[cb].ca,cmp2);
}
}
queue<node>q;
void Bfs(node s){
q.push(s);
node t;
int k,lst;
while (!q.empty()){
t=q.front();q.pop();
++ans;
for (k=0;a[bl[k+1].r].m<=t.p&&k<=cb;++k);
for (int i=1;i<=k;++i){
for (;bl[i].now<bl[i].ca;++bl[i].now)
if (bl[i].a[bl[i].now+1].l<=t.r) q.push(bl[i].a[bl[i].now+1]);
else break;
}
int lst=0;
for (int i=bl[k+1].now+1;i<=bl[k+1].ca;++i)
if (bl[k+1].a[i].m<=t.p&&bl[k+1].a[i].l<=t.r) q.push(bl[k+1].a[i]);
else bl[k+1].a[++lst]=bl[k+1].a[i];
bl[k+1].ca=lst;bl[k+1].now=0;
}
}
Abigail into(){
scanf("%d%d%d%lld%d",&sx,&sy,&a[0].p,&a[0].r,&n);
a[0].r=sqr(a[0].r);
for (int i=1;i<=n;++i){
scanf("%d%d%d%d%lld",&x,&y,&a[i].m,&a[i].p,&a[i].r);
a[i].r=sqr(a[i].r);
a[i].l=sqr((LL)x-sx)+sqr((LL)y-sy);
}
}
Abigail work(){
sort(a+1,a+1+n,cmp1);
Build(n);
Bfs(a[0]);
}
Abigail outo(){
printf("%d\n",ans-1);
}
int main(){
into();
work();
outo();
return 0;
}
博客围绕CH#46A题展开,题目是维护一个集合,根据给定条件取入元素,求集合稳定后的元素个数 - 1。解题用bfs模拟,将元素按m排序,再分块并按特定条件排序,查询时按规则删除元素,保证时间复杂度为O(n√n),还提到类似题BZOJ3276分块做法会TLE,需线段树。
刷题记录——CH#46A & BZOJ3276 磁力块(bfs+分块)&spm=1001.2101.3001.5002&articleId=89889638&d=1&t=3&u=42a3ed76bfa0486e84037d28493d3e3a)
984

被折叠的 条评论
为什么被折叠?



