12.12日记
CF
- 1234D:https://codeforces.com/problemset/problem/1234/D
其实直接对每个字母建一个树状数组,建26个即可。每次询问区间和,如果不为0,说明有这个字母,答案+1。时间复杂度\(O(26n\log n)\)
#include
using namespace std;
const int M=1e5+20;
int c[27][M],n;
char s[M];
inline int lowbit(int x){return x&(-x);}
inline void operate(int pos,int k){
for (int i=pos;i<=n;i+=lowbit(i))
c[s[pos]-'a'][i]+=k;
}
inline int query(int ch,int x){//1-x的和
int ans=0;
for(int j=x;j;j-=lowbit(j))
ans+=c[ch][j];
return ans;
}
inline int BITquery(int l,int r){
int ans=0;
for(int i=0;i<=25;++i)
ans+=(query(i,r)!=query(i,l-1));
return ans;
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;++i)
operate(i,1);
int q;
scanf("%d",&q);
for(int i=1;i<=q;++i){
int op;
scanf("%d",&op);
if (op==1){
int pos;
char sc[2];
scanf("%d%s",&pos,sc);
operate(pos,-1);
s[pos]=sc[0];
operate(pos,1);
}
else{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",BITquery(l,r));
}
}
return 0;
}
- 1185C2:https://codeforces.com/problemset/problem/1185/C2
这道题可以转化成:1-i区间内,挑出尽可能多的数,同时保证和 就是直接设置tot数组,存储目前为止,各个数字出现的次数。这样每次都从小往大暴力统计和,找到可以挑出的数的最大个数,再一减就得到答案了。 时间复杂度\(O(100n)\)。 还有一个\(O(n\log ^2n)\)的做法,就是首先读入后排序,然后再按原来顺序依次读入数据,建立树状数组,放到对应的排序后的位置上,然后维护区间和(和区间数的个数,相当于两个树状数组),之后二分询问区间和(1-x),找到最靠右的x,满足区间和 要求1-i区间的数,满足删掉一个之后,所有数出现次数相同。求出最大的i。 思路:开1e5个set,s[i]存放出现次数为i的数都有哪些。另外再开数组存储每个数出现的次数(即对应的集合)。再记录出现次数的最大值mx,那么满足条件只有两种情况: 那么这题就秒了。复杂度\(O(n\log n)\)。#include
#include
明日计划