洛谷P14426 [JOISC 2014] 稻草人 / Scarecrows 题解 CDQ分治

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

解题思路参考自 ningyy大佬的这篇博客

受到博客启发,我按照自己的思路,开两棵线段树解决了本题。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;

struct Point {
    int x, y;
} a[maxn];
int n;
long long ans;

struct Segtree {
    #define lson l, mid, u<<1
    #define rson mid+1, r, u<<1|1
    int t_max[maxn<<2], t_sum[maxn<<2];
    void push_up(int u) {
        t_max[u] = max(t_max[u<<1], t_max[u<<1|1]);
        t_sum[u] = t_sum[u<<1] + t_sum[u<<1|1];
    }
    void add(int p, int val, int l, int r, int u) {
        if (l == r) {
            t_sum[u] += val;
            t_max[u] += val;
            return;
        }
        int mid = l + r >> 1;
        (p <= mid) ? add(p, val, lson) : add(p, val, rson);
        push_up(u);
    }
    int query_max(int L, int R, int l, int r, int u) {
        if (L <= l && r <= R) return t_max[u];
        int res = 0, mid = l + r >> 1;
        if (L <= mid) res = max(res, query_max(L, R, lson));
        if (R > mid) res = max(res, query_max(L, R, rson));
        return res;
    }
    int query_sum(int L, int R, int l, int r, int u) {
        if (L <= l && r <= R) return t_sum[u];
        int res = 0, mid = l + r >> 1;
        if (L <= mid) res += query_sum(L, R, lson);
        if (R > mid) res += query_sum(L, R, rson);
        return res;
    }
    void clean(int l, int r, int u) {
        if (t_max[u] == 0 && t_sum[u] == 0) return;
        t_max[u] = t_sum[u] = 0;
        if (l == r) return;
        int mid = l + r >>1;
        clean(lson);
        clean(rson);
    }
} tsum, tmax;

void lsh() {
    vector<int> v;
    for (int i = 1; i <= n; i++) v.push_back(a[i].x);
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    for (int i = 1; i <= n; i++)
        a[i].x = lower_bound(v.begin(), v.end(), a[i].x) - v.begin() + 1;
    v.clear();
    for (int i = 1; i <= n; i++) v.push_back(a[i].y);
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    for (int i = 1; i <= n; i++)
        a[i].y = lower_bound(v.begin(), v.end(), a[i].y) - v.begin() + 1;
}

void cdq(int l, int r) {
    if (l >= r)
        return;
    int mid = l + r >> 1;
    cdq(l, mid);
    cdq(mid+1, r);
    sort(a+l, a+mid+1, [](auto a, auto b) {
        return a.y < b.y;
      });
    sort(a+mid+1, a+r+1, [](auto a, auto b) {
        return a.y < b.y;
      });
    tsum.clean(1, n, 1);
    tmax.clean(1, n, 1);
    stack<int> stk;
    set<int> st;
    int j = l, i = mid+1;
    for (; i <= r; i++) {
        for (; j <= mid && a[j].y <= a[i].y; j++) {
            while (!stk.empty() && a[stk.top()].x < a[j].x) {
                tsum.add(a[stk.top()].y, -1, 1, n, 1);
                stk.pop();
            }
            stk.push(j);
            tsum.add(a[j].y, 1, 1, n, 1);
        }
        int L = tmax.query_max(1, a[i].x, 1, n, 1);
        int cnt = tsum.query_sum(L, a[i].y, 1, n, 1);
        ans += cnt;
        tmax.add(a[i].x, a[i].y, 1, n, 1);
        st.insert(a[i].y);
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &a[i].x, &a[i].y);
    lsh();
    sort(a+1, a+n+1, [](auto a, auto b) {
        return a.x < b.x;
      });
    cdq(1, n);
    printf("%lld\n", ans);
    return 0;
}
posted @ 2026-01-15 00:32  quanjun  阅读(4)  评论(0)    收藏  举报