首页 > 其他分享 >abc343F 区间第2大的出现次数

abc343F 区间第2大的出现次数

时间:2024-03-17 16:24:40浏览次数:20  
标签:cnt int auto ret 次数 build 区间 query abc343F

给定数组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 namespace std;
#define int long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=b;i>=a;i--)

const int N = 200005;
int n, Q, d[4*N];
map<int,int> cnt[4*N];

void pushup(int x) {
    cnt[x].clear();
    for (auto [k,v] : cnt[2*x+1]) cnt[x][k] += v;
    for (auto [k,v] : cnt[2*x+2]) cnt[x][k] += v;
    while (cnt[x].size() > 2) {
        cnt[x].erase(cnt[x].begin());
    }
}
void build(int x, int l, int r) {
    if (l+1 == r) {
        cin >> d[x];
        cnt[x][d[x]] = 1;
        return;
    }
    int m = (l+r) / 2;
    build(2*x+1, l, m);
    build(2*x+2, m, r);
    pushup(x);
}
void update(int x, int l, int r, int u, int v) {
    if (l+1 == r) {
        d[x] = v;
        cnt[x].clear();
        cnt[x][d[x]] = 1;
        return;
    }
    int m = (l+r) / 2;
    if (u < m)
        update(2*x+1, l, m, u, v);
    else
        update(2*x+2, m, r, u, v);
    pushup(x);
}
map<int,int> query(int x, int l, int r, int L, int R) {
    map<int,int> ret;
    if (R <= l || r <= L) return ret;
    if (L <= l && r <= R) return cnt[x];
    int m = (l+r) / 2;
    map<int,int> z1 = query(2*x+1, l, m, L, R);
    map<int,int> z2 = query(2*x+2, m, r, L, R);
    for (auto [k,v] : z1) ret[k] += v;
    for (auto [k,v] : z2) ret[k] += v;
    while (ret.size() > 2) {
        ret.erase(ret.begin());
    }
    return ret;
}
void solve() {
    cin >> n >> Q;
    build(0, 1, n+1);
    rep(i,1,Q) {
        int op, x, y;
        cin >> op >> x >> y;
        if (op == 1) {
            update(0, 1, n+1, x, y);
        } else {
            auto t = query(0, 1, n+1, x, y+1);
            if (t.size() < 2) {
                cout << 0 << "\n";
            } else {
                auto it = t.begin();
                cout << it->second << "\n";
            }
        }
    }
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

标签:cnt,int,auto,ret,次数,build,区间,query,abc343F
From: https://www.cnblogs.com/chenfy27/p/18078714

相关文章

  • 435. 无重叠区间c
    typedefstructnode{intleft;intright;}bounds;intcmp(constvoid*a,constvoid*b){bounds*x=(bounds*)a;bounds*y=(bounds*)b;if(x->right>y->right)return1;return-1;}interaseOverlapIntervals(int**interva......
  • lc795 区间子数组个数
    给定数组nums[n]和两个整数left,right,找出nums中连续非空、并且最大元素在[left,right]范围内的子数组,统计所有满足条件子数组的个数。1<=n<=1e5;0<=nums[i]<=1e9;0<=left<=right<=1e9;保证答案在int内枚举每个元素作为最大元素的情况,统计对应的子数组数量,如果arr[i]在允许范......
  • Dictionary计算字符出现的次数
    stringstr="两只老虎,两只老虎,跑得快,跑得快。一只没有耳朵,一只没有尾巴,真奇怪,真奇怪。";Dictionary<char,int>dic=newDictionary<char,int>();for(inti=0;i<str.Length;i++){if(!dic.ContainsKey(str[i])......
  • P3374 【模板】树状数组 动态求连续区间和 刷题笔记
    我们创建如下的树状数组来辅助操作该数组每个s[i]处于第几层取决于其二进制最后低位的1处于从右往左数第几列显然所有奇数的最右边一位都是1即其最低位的1处于右边第一列所以所有的奇数处于第一层而2,6,10,14的最低位1处于右边第二列 所以这些数处于第二层 8的最......
  • lc327 区间和的个数
    给定数组nums[n]和整数lower与upper,求nums[n]中,元素之和在[lower,upper]范围内的子数组个数。1<=n<=1e5;nums[i]在int范围内;-1e5<=lower<=upper<=1e5;答案在int范围内子数组的和可以用前缀和来快速求出,假设当前位置对应的前缀和为y,前面某处对应的前缀和为x,满足lower<=y-x<=u......
  • 矩阵中移动的最大次数.18076762
    矩阵中移动的最大次数给你一个下标从0开始、大小为mxn的矩阵grid,矩阵由若干正整数组成。你可以从矩阵第一列中的任一单元格出发,按以下方式遍历grid:从单元格(row,col)可以移动到(row-1,col+1)、(row,col+1)和(row+1,col+1)三个单元格中任一......
  • JS代码——统计字符串中每个字符出现的次数
    要求:输入一个字符串,输出每个字符各自出现的次数一、代码区域二、效果截图注: 博主每天记录自己所学,如有写的不好之处,希望您能不吝赐教,给我一些关于这个项目的意见和建议。各位的宝贵意见将对我产生深远的影响,我将认真倾听并尽力改进。谢谢各位~~......
  • C++ | 蓝桥题库区间或(位运算)
    一开始看题解很晕,这里采用前缀和方式的思想是:按位贡献,将答案分成32份(1e9最多32位二进制数)这样才有的prefix[32][N]前缀和数组,求的是第i位数第w位上的和。(1<<w)1左移w位相当于2的w次方,prefix[w][r]-prefix[w][l-1]相当于[l,r]这段距离上有1就让ans加上1,没有就不加。#inc......
  • 蓝桥练习题-K倍区间
    16.k倍区间-蓝桥云课(lanqiao.cn)首先,看到这个题,想到暴力求解,但显然,数据过大,暴力法过不了;然后看到了一个办法:对所有元素的前缀和取K的模,若s[i],s[j]相同,则在j-1到i的区间内,区间和为K的倍数。C++代码:#include<iostream>#include<queue>usingnamespacestd;ty......
  • 2024/3/11打卡管道(14届蓝桥杯省赛)——二分+区间合并
    目录题目思路代码题目有一根长度为 len的横向的管道,该管道按照单位长度分为 len 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。一开始管道是空的,位于 Li 的阀门会在  时刻打开,并不断让水流入管道。对于位于  的阀门,它流入的水在 时刻会使得......