chenfy27的刷题记录

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

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 on   chenfy27  阅读(4)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示