Solution to a problem P2163 SHOI2007 gardener troubles

Reprinted from: https://lornd.top/index.php/archives/25/

The number of two-dimensional point (Fenwick tree) exercises.

Topic link: P2163 SHOI2007 gardener troubles

Subject to the effect

Given plane rectangular coordinate system \ (n-\) points with \ (m \) times asked each time to ask a rectangular internal (including sides) the number of points.

\ (n-, m \ Le. 5 \ ^. 5 Times 10 \) , horizontal and vertical coordinates of the point \ (0 \ Le x_i, y_i \ Le. 7 10 ^ \) , which gives the lower left apex of each rectangle \ ((a_i, B_i) \) and the upper right apex \ ((C_i, D_i) \) .

Problem-solving ideas

If we can find the vertex \ ((x_i, y_i) \ ) the number of points the lower left \ (f ((x_i, y_i)) \) , then according to the prefix and thought, for a rectangular \ (((a_i , B_i), (C_i, D_i)) \) : clearly be: \ [ANS = F ((C_i, D_i)) - F ((a_i -. 1, D_i)) - F ((C_i, B_i -1) ) + f ((a_i - 1 , b_i - 1)) \]

So we will be transformed into a question seeking a point of the bottom left of the number of problem points ( two-dimensional problem of the number of points ), consider how to deal with it.


Point number two-dimensional problem

We consider offline, we put all inquiries to the corresponding abstract points, plus any original point of the coordinate system, and to keep them together (X \) \ axis as a first key, \ (Y \) axis coordinates of the second sort key, and then from left to right handle every point, so as to ensure that we can only point to a number of inquiries each time left.

For \ (Y \) axis, we build a tree array, \ (the BIT [I] \) , which is the original array \ (A [I] \) , represents all points to the currently considered, the vertical coordinates of not more than \ (i \) is the number of points.

In dealing with the point, if you encounter any original point of the coordinate system, can be considered to modify the operating Fenwick tree, so that \ (A [i] \) plus one; if the point of asking encountered, the query is equivalent to \ (a [1 \ sim i ] \) and.

Since the definition of Fenwick tree original array, we would simply point below the number of inquiries, and because we follow the \ (x \) for processing axis direction, we will only count to ask the point to the left point, so we the result is the number of points the lower left point of the query.


Back to the original question, we now find every point of \ (f ((x_i, y_i )) \) value, but the key is a rectangle corresponding to the four points, each point when the result of calculating the final answer addition and subtraction cases, different, and more than a rectangle, confused how do we prevent this?

First, we can add a point for each attribute \ (ID \) represents the number of points belonging to the first rectangle, in order to facilitate resolution, we can original point of the coordinate system \ (ID \) assigned \ (0 \) , so that we can ensure that each point corresponds to a maximum of a rectangle.

Secondly, on the issue of addition and subtraction, look at a point we do not know it when calculating the final answer is to add a minus, but when we see it placed in the rectangle, we can find a lower left corner and upper right corner of the rectangle the apex is plus, minus other point is , we can add an attribute for each point \ (flag = \ pm 1 \ ) to determine the addition and subtraction, so that when we deal with the answer to a single query only needs no brains plus It can, of course, multiplied by \ (Flag \) .

In this way, we can get the number of points in each of the rectangle.

But there is a problem: Fenwick tree we build is built on the ordinate, the subscript range corresponds to the vertical axis of the range, the data is too large, how do? Ordinate directly be discrete !

The final code is as follows:

#include <cstdio>
#include <algorithm>

const int MAXN = 5e5 + 1;

int n, m, a, b, c, d, cnt;
int res[MAXN * 5];
int BIT[MAXN * 5];
int ans[MAXN];

struct node {
    int num, place;
    node(int nn = 0, int pp = 0) {
        num = nn;
        place = pp;
    }
    bool operator < (const node &another) const {
        return num < another.num;
    }
}temp[MAXN * 5];

struct point {
    int x, y, id, flag;
    point (int xx = 0, int yy = 0, int ii = 0, int ff = 0) {
        x = xx;
        y = yy;
        id = ii;
        flag = ff;
    }
    bool operator < (const point another) const {
        if (x == another.x){
            if (y == another.y)
                return id < another.id;
            else
                return y < another.y;
        }
        else
            return x < another.x;
    }
}arr[MAXN * 5];

void discretizate() {
    std::sort(temp + 1, temp + cnt + 1);
    int cur = 1;
    for (int i = 1; i <= cnt; ++i) {
        res[temp[i].place] = cur;
        if (temp[i].num != temp[i + 1].num)
            ++cur;
    }
    for (int i = 1; i <= cnt; ++i) {
        arr[i].y = res[i];
    }
}

int lowbit(int key) {
    return key & (-key);
}

void modify(int place, int key) {
    for (; place <= n; place += lowbit(place)) {
        BIT[place] += key;
    }
}

int query(int place) {
    int tmp = 0;
    for (; place; place -= lowbit(place)) {
        tmp += BIT[place];
    }
    return tmp;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &a, &b);
        arr[++cnt] = point(a, b);
        temp[cnt] = node(b, cnt);
    }
    for (int i = 1; i <= m; ++i) {
        scanf("%d%d%d%d", &a, &b, &c, &d); //将一个矩形抽象成四个点加入序列
        arr[++cnt] = point(a - 1, b - 1, i, 1);
        temp[cnt] = node(b - 1, cnt);
        arr[++cnt] = point(a - 1, d, i, -1);
        temp[cnt] = node(d, cnt);
        arr[++cnt] = point(c, b - 1, i, -1);
        temp[cnt] = node(b - 1, cnt);
        arr[++cnt] = point(c, d, i, 1);
        temp[cnt] = node(d, cnt);
    }
    discretizate(); //离散化
    std::sort(arr + 1, arr + cnt + 1);
    for (int i = 1; i <= cnt; ++i) {
        if (arr[i].id == 0)
            modify(arr[i].y, 1);
        else
            ans[arr[i].id] += arr[i].flag * query(arr[i].y);
    }
    for (int i = 1; i <= m; ++i) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/lornd/p/11331400.html