蓝书(算法竞赛进阶指南)刷题记录——CH#46A磁力块(bfs+分块)

版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/89889638

题目: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) 和其它 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) .现在维护一个集合初始只有元素 a 0 a_0 ,然后对于集合中每一个元素 a i a_i 可以把所有满足条件的 a j a_j 取入集合.问集合稳定后的元素个数 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

1 n 2.5 1 0 5 1\leq n\leq 2.5*10^5 .

这道题的运行过程完全就是bfs的板子,所以直接用bfs来模拟即可把问题转化为一个元素会让哪些元素加入集合.

为了解决这个问题,我们先把所有元素按照 m m 排序,现在我们会发现所有满足 m j < p i m_j<p_i 的元素 j j 一定在一个左端点为1的区间内了.

那么如何找出这之中那些满足第一个条件的元素并删除呢?我们在把这个排好序的序列分块,每一块的内部再按照 ( x 0 x j ) 2 + ( y 0 y j ) 2 (x_0-x_j)^2+(y_0-y_j)^2 排序,然后每次查询整块的时候从开头开始删除(肯定是包含块开头连续的一段会被删除),不在整块内则暴力删除,这样做可以保证总时间复杂度为 O ( n n ) O(n\sqrt{n})

代码如下:

#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;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/89889638