代码模板

笛卡尔树

l 和 r 的lca 为区间RMQ

// https://codeforces.com/contest/1748/submission/181116336
std::vector<int> lc(n, -1), rc(n, -1), s;
for (int i = 0; i < n; i++) {
    while (!s.empty() && a[i] < a[s.back()]) {
        int x = s.back();
        rc[x] = lc[i];
        lc[i] = x;
        s.pop_back();
    }
    s.push_back(i);
}

while (s.size() > 1) {
    int x = s.back();
    s.pop_back();
    rc[s.back()] = x;
}
std::vector<int> stk;
std::vector<int> lc(n, -1), rc(n, -1);
for (int i = 0; i < n; ++i) {
    int last = -1;
    while (!stk.empty() && a[stk.back()] > a[i]) {
        last = stk.back();
        stk.pop_back();
    }
    lc[i] = last;
    if (stk.size()) {
        rc[stk.back()] = i;
    }
    stk.push_back(i);
}

树状数组

#include <bits/stdc++.h>

using i64 = long long;

constexpr int N = 2E5 + 5;

std::vector<int> fen1(N), fen2(N);

int fenl[N], fenr[N];

void add(int *fen, int x, int y) {
    for (int i = x + 1; i < N; i += i & -i) {
        fen[i - 1] += y;
    }
}

int sum(int *fen, int x) {
    int res = 0;
    for (int i = x; i; i = i & (i - 1)) {
        res += fen[i - 1];
    }
    return res;
}

int rangeSum(int *fen, int l, int r) {
    return sum(fen, r) - sum(fen, l);
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    for (auto &x : a) {
        add(fenr, x, 1);
    }

    i64 ans0 = 0, ans1 = 0;
    for (auto &x : a) {
        ans0 += 1LL * rangeSum(fenl, x + 1, N) * rangeSum(fenr, x + 1, N);
        ans1 += 1LL * sum(fenl, x) * sum(fenr, x);
        add(fenl, x, 1);
        add(fenr, x, -1);
    }

    std::cout << ans0 << " " << ans1 << '\n';
}

线段树

#include <bits/stdc++.h>

using i64 = long long;

constexpr int L = 4E5 + 5;

struct Info {
    i64 sum = 0;
    i64 act = 1;

    i64 tag = 0;
    void apply(i64 add) {
        sum += add * act;
        tag += add;
    }
} info[L];

Info operator+(Info a, Info b) {
    Info c;
    c.sum = a.sum + b.sum;
    c.act = a.act + b.act;
    return c;
}

void pull(int p) {
    info[p] = info[2 * p] + info[2 * p + 1];
}

void push(int p) {
    info[2 * p].apply(info[p].tag);
    info[2 * p + 1].apply(info[p].tag);
    info[p].tag = 0;
}

void rangeApply(int p, int l, int r, int x, int y, i64 t) {
    if (y <= l || r <= x) {
        return;
    }
    if (x <= l && r <= y) {
        info[p].apply(t);
        return;
    }
    int m = (l + r) / 2;
    push(p);
    rangeApply(2 * p, l, m, x, y, t);
    rangeApply(2 * p + 1, m, r, x, y, t);
    pull(p);
}

Info rangeQuery(int p, int l, int r, int x, int y) {
    if (y <= l || r <= x) {
        return Info();
    }
    if (x <= l && r <= y) {
        return info[p];
    }
    push(p);
    int m = (l + r) / 2;
    return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}

void out(int p, int l, int r) {
    if (r - l == 1) {
        std::cout << info[p].sum << " ";
        return;
    }
    push(p);
    int m = (l + r) / 2;
    out(2 * p, l, m);
    out(2 * p + 1, m, r);
}


int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<Info> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i].sum;
    }

    // build
    [&](this auto &&self, int p, int l, int r) -> void {
        if (r - l == 1) {
            info[p] = a[l];
            return;
        }
        int m = (l + r) / 2;
        self(2 * p, l, m);
        self(2 * p + 1, m, r);
        pull(p);
    } (1, 0, n);

    for (int i = 0; i < m; ++i) {
        int op, x, y;
        std::cin >> op >> x >> y;
        --x;
        
        if (op == 1) {
            i64 k;
            std::cin >> k;
        
            rangeApply(1, 0, n, x, y, {k});
        } else {
            std::cout << rangeQuery(1, 0, n, x, y).sum << "\n";
        }
    }

    return 0;
}

懒标记线段树

#include <bits/stdc++.h>

using i64 = long long;

constexpr int L = 4E5 + 5;

std::vector<int> len(L);
std::vector<int> cnt(L);
std::vector<int> tag(L);

void apply(int p) {
    tag[p] ^= 1;
    cnt[p] = len[p] - cnt[p];
}

void push(int p) {
    if (tag[p] == 0) {
        return;
    }
    tag[p] = 0;
    apply(2 * p);
    apply(2 * p + 1);
}

void pull(int p) {
    cnt[p] = cnt[2 * p] + cnt[2 * p + 1];
    // len[p] = len[2 * p] + len[2 * p + 1];
}

void modify(int p, int l, int r, int x, int y) {
    if (r <= x || y <= l) {
        return;
    }
    if (x <= l && r <= y) {
        apply(p);
        return;
    }
    push(p);
    int m = (l + r) / 2;
    modify(2 * p, l, m, x, y);
    modify(2 * p + 1, m, r, x, y);
    pull(p);
}

int query(int p, int l, int r, int x, int y) {
    if (r <= x || y <= l) {
        return 0;
    }
    if (x <= l && r <= y) {
        return cnt[p];
    }
    push(p);
    int m = (l + r) / 2;
    return query(2 * p, l, m, x, y) + query(2 * p + 1, m, r, x, y);
}

auto out(int p, int l, int r) -> void {
    if (r - l == 1) {
        std::cout << cnt[p] << ' ';
        return;
    }
    push(p);
    int m = (l + r) / 2;
    out(2 * p, l, m);
    out(2 * p + 1, m, r);
    if (p == 1) {
        std::cout << std::endl;
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    // build
    [&](this auto &&self, int p, int l, int r) -> void {
        len[p] = r - l;
        if (r - l == 1) {
            return;
        }
        int m = (l + r) / 2;
        self(2 * p, l, m);
        self(2 * p + 1, m, r);
    } (1, 0, n);

    for (int i = 0; i < m; ++i) {
        int c, a, b;
        std::cin >> c >> a >> b;
        --a;

        if (c == 0) {
            modify(1, 0, n, a, b);
        } else {
            std::cout << query(1, 0, n, a, b) << "\n";
        }
    }
}
posted @ 2026-04-04 15:10  filt  阅读(1)  评论(0)    收藏  举报