abc343F 区间第2大的出现次数

给定数组a[n],有Q组操作,格式为:

  • 1 p x,将a[p]修改为x;
  • 2 l r,查询区间[l,r]内第2大元素的出现次数。

1<=n,q<=2e5; 1<=a[i]<=1e9

用线段树维护各个区间的最大及次大元素的出现次数,合并时最多只保留两条记录。

#include <bits/stdc++.h>
using i64 = long long;

template<class Info>
struct SegmentTree {
    int n;
    std::vector<Info> info;
    SegmentTree():n(0) {}
    SegmentTree(int _n, Info v = Info()) {
        init(_n, v);
    }
    void init(int _n, Info v = Info()) {
        init(std::vector<Info>(_n, v));
    }
    template<class T>
    SegmentTree(std::vector<T> v) {
        init(v);
    }
    template<class T>
    void init(std::vector<T> v) {
        n = v.size();
        info.assign(4 << std::__lg(n), Info());
        std::function<void(int,int,int)> build = [&](int x, int l, int r) {
            if (l + 1 == r) {
                info[x] = v[l];
                return;
            }
            int m = (l + r) / 2;
            build(2*x+1, l, m);
            build(2*x+2, m, r);
            pushup(x);
        };
        build(0, 0, n);
    }
    void pushup(int x) {
        info[x] = info[2*x+1] + info[2*x+2];
    }
    void modify(int x, int l, int r, int p, const Info &v) {
        if (l + 1 == r) {
            info[x] = v;
            return;
        }
        int m = (l + r) / 2;
        if (p < m) {
            modify(2*x+1, l, m, p, v);
        } else {
            modify(2*x+2, m, r, p, v);
        }
        pushup(x);
    }
    void modify(int p, const Info &v) {
        modify(0, 0, n, p, v);
    }
    Info rangeQuery(int x, int l, int r, int L, int R) {
        if (R <= l || r <= L) {
            return Info();
        }
        if (L <= l && r <= R) {
            return info[x];
        }
        int m = (l + r) / 2;
        return rangeQuery(2*x+1, l, m, L, R) + rangeQuery(2*x+2, m, r, L, R);
    }
    Info rangeQuery(int L, int R) {
        return rangeQuery(0, 0, n, L, R);
    }
    template<class F>
    int findFirst(int x, int l, int r, int L, int R, F pred) {
        if (R <= l || r <= L || !pred(info[x])) {
            return -1;
        }
        if (l + 1 == r) {
            return l;
        }
        int m = (l + r) / 2;
        int res = findFirst(2*x+1, l, m, L, R, pred);
        if (res == -1) {
            res = findFirst(2*x+2, m, r, L, R, pred);
        }
        return res;
    }
    template<class F>
    int findFirst(int L, int R, F pred) {
        return findFirst(0, 0, n, L, R, pred);
    }
    template<class F>
    int findLast(int x, int l, int r, int L, int R, F pred) {
        if (R <= l || r <= L || !pred(info[x])) {
            return -1;
        }
        if (l + 1 == r) {
            return l;
        }
        int m = (l + r) / 2;
        int res = findLast(2*x+2, m, r, L, R, pred);
        if (res == -1) {
            res = findLast(2*x+1, l, m, L, R, pred);
        }
        return res;
    }
    template<class F>
    int findLast(int L, int R, F pred) {
        return findLast(0, 0, n, L, R, pred);
    }
};

struct Info {
    int max1, cnt1, max2, cnt2;
    Info(int v=0):max1(v),cnt1(1),max2(0),cnt2(0) {}
    friend Info operator+(const Info &a, const Info &b) {
        Info ans;
		std::map<int,int> mp;
		if (a.max1 > 0) mp[a.max1] += a.cnt1;
		if (a.max2 > 0) mp[a.max2] += a.cnt2;
		if (b.max1 > 0) mp[b.max1] += b.cnt1;
		if (b.max2 > 0) mp[b.max2] += b.cnt2;
		auto it = mp.rbegin();
		if (it != mp.rend()) {
			ans.max1 = it->first;
			ans.cnt1 = it->second;
			++it;
			if (it != mp.rend()) {
				ans.max2 = it->first;
				ans.cnt2 = it->second;
			}
		}
        return ans;
    }
};

void solve() {
    int n, q;
    std::cin >> n >> q;
    std::vector<i64> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    SegmentTree<Info> seg(a);
    for (int i = 0; i < q; i++) {
        int op, x, y;
        std::cin >> op >> x >> y;
        if (op == 1) {
			seg.modify(x-1, Info(y));
        } else if (op == 2) {
			std::cout << seg.rangeQuery(x-1, y).cnt2 << "\n";
        }
    }
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}
posted @ 2024-03-17 16:11  chenfy27  阅读(1)  评论(0编辑  收藏  举报