CF1234D
CF1234D
链接:
https://codeforces.com/problemset/problem/1234/D
题目大意:
给你一个字符串s,你需要完成如下q次询问
- 把 s 的第 p 位改为 c。输入中表述为
1 p c
- 求 s 从 l 到 r 出现了多少种不同字符。在输入中表述为
2 l r
。
所有字符都是小写字母并且:
思路:
遇到此类查询与修改问题,首先不能想着去暴力,该题目暴力的复杂度可达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))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】