「Codeforces 762E」Radio Stations 题解

主要思路

可以把整个思路转换为 CDQ 分治下的二位数点。\(x\)轴就代表正常的物理距离的轴,然后\(y\)轴就代表信号接收的轴,把一个询问拆掉成为容斥的形式即可。

代码

// CF762E.cpp
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int MAX_N = 1e5 + 20, MAX_F = 1e4 + 200;

int n, k, tree[MAX_F], qtot;
ll ans;

struct station
{
    int x, r, f;
    bool operator<(const station &target) const { return r > target.r; }
} stats[MAX_N];

struct query
{
    int type, x, y, w;
    bool operator<(const query &q) { return x < q.x || (x == q.x && type < q.type); }
} queries[MAX_N * 5], tmp[MAX_N * 5];

bool compareByLowerBound(station a, station b) { return a.x - a.r < b.x - b.r; }

bool compareByUpperBound(station a, station b) { return a.x + a.r < b.x + b.r; }

inline int lowbit(int x) { return x & -x; }

void update(int x, int d)
{
    for (; x <= MAX_F - 1; x += lowbit(x))
        tree[x] += d;
}

int query(int x)
{
    int ans = 0;
    for (; x; x -= lowbit(x))
        ans += tree[x];
    return ans;
}

void clear(int x)
{
    for (; x <= MAX_F - 1; x += lowbit(x))
        tree[x] = 0;
}

void cdq(int l, int r)
{
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    cdq(l, mid), cdq(mid + 1, r);
    int ptr1 = l, ptr2 = mid + 1, tot = l - 1;
    while (ptr1 <= mid && ptr2 <= r)
        if (queries[ptr1] < queries[ptr2])
        {
            if (queries[ptr1].type == 0)
                update(queries[ptr1].y, 1);
            tmp[++tot] = queries[ptr1++];
        }
        else
        {
            if (queries[ptr2].type == 1)
                ans += query(queries[ptr2].y) * queries[ptr2].w;
            tmp[++tot] = queries[ptr2++];
        }
    while (ptr1 <= mid)
        tmp[++tot] = queries[ptr1++];
    while (ptr2 <= r)
    {
        if (queries[ptr2].type == 1)
            ans += query(queries[ptr2].y) * queries[ptr2].w;
        tmp[++tot] = queries[ptr2++];
    }
    for (int i = l; i <= r; i++)
    {
        if (queries[i].type == 0)
            clear(queries[i].y);
        queries[i] = tmp[i];
    }
}

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d", &stats[i].x, &stats[i].r, &stats[i].f);
    sort(stats + 1, stats + 1 + n);
    for (int i = 1; i <= n; i++)
    {
        station st = stats[i];
        int x0 = st.x - st.r, x1 = st.x + st.r;
        int y0 = max(1, st.f - k), y1 = st.f + k;
        queries[++qtot] = {1, x0 - 1, y0 - 1, 1};
        queries[++qtot] = {1, x0 - 1, y1, -1};
        queries[++qtot] = {1, x1, y0 - 1, -1};
        queries[++qtot] = {1, x1, y1, 1};
        queries[++qtot] = {0, st.x, st.f, 0};
    }
    cdq(1, qtot);
    printf("%lld", ans);
    return 0;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *