洛谷U644377 平面点对 题解 树套树(权值线段树 套 权值线段树)

题目链接:https://www.luogu.com.cn/problem/U644377

空间有点大,把坐标范围从 \([-10^9,10^9]\) 缩小到 \([-10^5,10^5]\) 了。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4  + 5, maxm = 6e7 + 5, inf = 1e5;

int n, Q, rt = 1;

struct Segt1 {
    int ls[maxm], rs[maxm], tr[maxm], idx = 1;

    void push_up(int u) {
        tr[u] = tr[ls[u]] + tr[rs[u]];
    }

    void add(int y, int val, int l, int r, int &u) {
        if (!u) u = ++idx;
        if (l == r) {
            tr[u] += val;
            return;
        }
        int mid = l + r >> 1;
        (y <= mid) ? add(y, val, l, mid, ls[u]) : add(y, val, mid+1, r, rs[u]);
        push_up(u);
    }

    int query(int L, int R, int l, int r, int u) {
        if (!u) return 0;
        if (L <= l && r <= R) return tr[u];
        int res = 0, mid = l + r >> 1;
        if (L <= mid) res += query(L, R, l, mid, ls[u]);
        if (R > mid) res += query(L, R, mid+1, r, rs[u]);
        return res;
    }

} segt1;

struct Segt2 {
    int ls[maxm], rs[maxm], tr[maxm], idx = 1;

    void add(int x, int y, int val, int l, int r, int &u) {
        if (!u) u = ++idx;
        segt1.add(y, val, -inf, inf, tr[u]);
        if (l == r) return;
        int mid = l + r >> 1;
        (x <= mid) ? add(x, y, val, l, mid, ls[u]) : add(x, y, val, mid+1, r, rs[u]);
    }

    int query(int x1, int x2, int y1, int y2, int l, int r, int u) {
        if (!u) return 0;
        if (x1 <= l && r <= x2)
            return segt1.query(y1, y2, -inf, inf, tr[u]);
        int res = 0, mid = l + r >> 1;
        if (x1 <= mid)
            res += query(x1, x2, y1, y2, l, mid, ls[u]);
        if (x2 > mid)
            res += query(x1, x2, y1, y2, mid+1, r, rs[u]);
        return res;
    }

} segt2;

struct Point {
    int x, y;
} point[maxn];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &point[i].x, &point[i].y);
        segt2.add(point[i].x, point[i].y, 1, -inf, inf, rt);
    }
    scanf("%d", &Q);
    while (Q--) {
        int op;
        scanf("%d", &op);
        if (op == 1) {
            int p, x, y;
            scanf("%d%d%d", &p, &x, &y);
            segt2.add(point[p].x, point[p].y, -1, -inf, inf, rt);
            point[p] = {x, y};
            segt2.add(point[p].x, point[p].y, 1, -inf, inf, rt);
        }
        else {
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &x2, &y1, &y2);
            int ans = segt2.query(x1, x2, y1, y2, -inf, inf, rt);
            printf("%d\n", ans);
        }
    }
    return 0;
}
posted @ 2026-01-01 16:46  quanjun  阅读(2)  评论(0)    收藏  举报