AcWing250 磁力块(分块)

本题仔细分析发现也是一个二维偏序问题,并且因为强制在线,所以不能用莫队来做,因此考虑分块的做法

这道题,因为题目第一个要求是距离小于半径,因此我们直接算出距离后,通过对距离排序,之后分块

这样的分块就会产生一个性质,在某些块中的所有半径都小于r,而在边界块中,则使用暴力。

在块中我们按质量排序

之后我们只需要给每个块分配一个指针,用于判断质量和吸力的关系,这个指针会一直往后推,不用回溯。

这题还可以替换磁力块,其实就相当于bfs,将已经吸入的都可以当作x,y这个点,只要最后队列空了,说明就结束了

AcWing250 磁力块(分块)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int mod=1e9+7;
struct node{
    ll dis,m;
    ll r,p;
}s[2*N+10],d[510][510];
ll sign[5050];
int e[5050];
int st[5050][5050];
int cnt[5050];
int n,block;
ll x,y,x2,y2;
bool cmpa(node a,node b){
    return a.dis<b.dis;
}
bool cmpb(node a,node b){
    return a.m<b.m;
}
void init(){
    int i;
    for(i=1;i<=n;i++){
        cin>>x2>>y2>>s[i].m>>s[i].p>>s[i].r;
        s[i].dis=(x2-x)*(x2-x)+(y2-y)*(y2-y);
        s[i].r*=s[i].r;
    }
    block=sqrt(n);
    sort(s+1,s+1+n,cmpa);
    for(i=1;i<=n;i++){
        d[(i-1)/block+1][(i-1)%block]=s[i];
        sign[(i-1)/block+1]=s[i].dis;
    }
    for(i=1;i<=(n-1)/block+1;i++){
        if(i*block<=n)
            e[i]=block;
        else
            e[i]=n%block;
        sort(d[i],d[i]+e[i],cmpb);
    }
}
bool check(ll a,ll b){
    return a<=b;
}
void bfs(){
    queue<node> q;
    q.push(s[0]);
    st[0][0]=1;
    while(q.size()){
        node t=q.front();
        q.pop();
        int i;
        for(i=1;i<=(n-1)/block+1;i++){
            if(sign[i]<=t.r){
               while(cnt[i]<e[i]&&check(d[i][cnt[i]].m,t.p)){
                    if(!st[i][cnt[i]]){
                        st[i][cnt[i]]=1;
                        q.push(d[i][cnt[i]]);
                    }
                    cnt[i]++;
                }
            }
            else{
                for(int j=0;j<e[i];j++){
                    if(d[i][j].dis<=t.r&&d[i][j].m<=t.p){
                        if(!st[i][j]){
                            q.push(d[i][j]);
                            st[i][j]=1;
                        }
                    }
                }
                break;
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin>>x>>y>>s[0].p>>s[0].r>>n;
    s[0].r*=s[0].r;
    init();
    bfs();
    int i;
    ll ans=0;
    for(i=1;i<=(n-1)/block+1;i++){
        for(int j=0;j<e[i];j++){
            if(st[i][j])
                ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

上一篇:【牛客练习赛22 C】


下一篇:Array K-Coloring