Loading

BZOJ-3276 磁力块

磁力

分块

整个过程像 bfs,就把能吸引的加入队列,然后一个个判断能不能吸引,暴力的复杂度是 \(O(n^2)\)

可以通过分块的技术,先按照质量分块,在块内再对距离进行分块,每次搜索的时候一定存在一个 k,使得 \([1,k-1]\) 的块内,所有的点的质量都符合条件,同时 \([k+1,t]\) 的块内所有点的质量都大于吸引力,而对于第 k 个块,就只能暴力判断

在一个块中,因为我们是对距离排序,所以直接从左到右找,如果找成功了,就把块的左边界缩减一下

对于第 k 个块,只能暴力跑,我这里是用一个 \(vis\) 来标记是否吸引过

bzoj 的数据比 acwing 上边的数据弱

acwing该题的地址

acwing 的题得提前预处理距离,就不用每次算,能减少一点常数,因为都是和所在位置进行距离判断,所以直接预处理就好

时间复杂度是 \(O(n \sqrt{n})\)

感觉我这种分块写法虽然容易写,但是常数确实大,空间消耗也大

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 250000 + 10;
const double eps = 1e-8;
int R[maxn], L[maxn], pos[maxn], vis[maxn];
double hm[maxn];

struct node
{
    double x, y, p, m, r, dis;
    node(){}
    node(double _x, double _y, double _p, double _m, double _r){x = _x; y = _y; r = _r; p = _p; m = _m;}
}num[maxn];
vector<node>q;

bool cmp_m(const node& a, const node& b)
{
    return a.m < b.m;
}

double dis(const node& a, const node& b)
{
    double xx = a.x - b.x;
    double yy = a.y - b.y;
    return sqrt(xx * xx + yy * yy);
}

bool cmp_dis(const node& a, const node& b)
{
    return a.dis < b.dis;
}

int dcmp(double x)
{
    return (x > eps) - (x < -eps);
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    double x, y, p, r, m;
    int n;
    cin >> x >> y >> p >> r >> n;
    q.push_back(node(x, y, p, 100, r));
    for(int i=1; i<=n; i++)
    {
        cin >> x >> y >> m >> p >> r;
        num[i] = node(x, y, p, m, r);
        num[i].dis = dis(num[i], q[0]);
    }
    sort(num + 1, num + n + 1, cmp_m);
    int t = sqrt(n);
    for(int i=1; i<=t; i++)
    {
        L[i] = R[i-1] + 1;
        R[i] = i * t;
    }
    if(R[t] < n)
    {
        t++;
        L[t] = R[t-1] + 1;
        R[t] = n;
    }

    for(int i=1; i<=t; i++)
    {
        for(int j=L[i]; j<=R[i]; j++)
            pos[j] = i;
        hm[i] = num[R[i]].m;
        sort(num + L[i], num + R[i] + 1, cmp_dis);
    }

    for(int i=0; i<q.size(); i++)
    {
        int tp = 1;
        while(tp < t && dcmp(q[i].p - hm[tp]) == 1) tp++;
        for(int j=1; j<tp; j++)
        {
            for(int k=L[j]; k<=R[j]; k++)
            {
                if(vis[k]) {L[j]++; continue;}
                if(dcmp(q[i].p - num[k].m) >= 0 && dcmp(q[i].r - num[k].dis) >= 0)
                {
                    q.push_back(num[k]);
                    L[j]++;
                }
                else break;
            }
        }
        for(int j=L[tp]; j<=R[tp]; j++)
        {
            if(vis[j]) continue;
            if(dcmp(q[i].p - num[j].m) >= 0 && dcmp(q[i].r - num[j].dis) >= 0)
            {
                vis[j] = 1;
                q.push_back(num[j]);
            }
        }
    }
    
    cout << q.size() - 1 << endl;
    return 0;
}
posted @ 2022-05-20 21:33  dgsvygd  阅读(21)  评论(0编辑  收藏  举报