CF1234D

CF1234D

链接:

https://codeforces.com/problemset/problem/1234/D

题目大意:

给你一个字符串s,你需要完成如下q次询问

  • s 的第 p 位改为 c。输入中表述为 1 p c
  • slr 出现了多少种不同字符。在输入中表述为 2 l r

所有字符都是小写字母并且:

|s|105,q<=105

思路:

遇到此类查询与修改问题,首先不能想着去暴力,该题目暴力的复杂度可达1e10,是不可观的,我们发现不同字符,最多也就26种,所以对于这种统计不同字符的题目,一种比较好的解题思路是分桶,26个字母26个桶,对每个桶逐一操作;

如何实现这两个操作?,这道题有两种办法,一种是树状数组/线段树,另一种是set+二分(STL大法),下面代码与思路用的是set+二分的方法,

  • 修改操作: 对于每个修改前字符的桶 erase掉的这个位置p,对于修改的字符的桶加入这个位置p

  • 查询操作: 对每个桶的set二分,因为set是单调的支持二分,二分他的lower_bound(l),也就是第一个比l大或者等于的位置,判断这个位置是否超过R,如果没有超过,说明该字符在区间内,可以计数器++

代码:

set<int> pos[26];
void solve(){
    string s;
    cin >> s;
    int n = s.size();
    s = " " +s;
    for(int i = 1;i<=n;i++){
        pos[s[i]-'a'].insert(i);
    }
    int q;
    cin >> q;
    while(q--){
        int op;
        cin >> op;
        if(op==2){
            int l,r;
            cin >> l >> r;
            int cnt = 0;
            for(int i = 0; i < 26;i++){
                auto id = pos[i].lower_bound(l);
                if(id==pos[i].end()) continue;

                if(*id<=r) cnt++;
            }
            cout <<cnt << endl;
        }else{
            int idx;
            char c;
            cin >> idx >> c;
            int yb = s[idx];
            pos[yb-'a'].erase(idx);
            pos[c-'a'].insert(idx);
            s[idx] = c;
        }
    }
}

时间复杂度:

O(m * log(n))

posted @   GsGXT  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示