题目传送门
#include<iostream>
#include<set>
#include<cstring>
using namespace std;
int n,m;
char c[100005];
inline int read()
{
register int x=0;
register char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
return x;
}
struct tree
{
int l,r;
mutable int v;
bool operator<(const tree &o)const
{
return l<o.l;
}
};
set<tree>t;
inline auto split(int m)
{
auto it=t.upper_bound({m,0,0});
it--;
if(it->l==m)return it;
int l=it->l,r=it->r,v=it->v;
t.erase(it);
t.insert({l,m-1,v});
return t.insert({m,r,v}).first;
}
inline void assign(int l,int r,int v)
{
auto itr=split(r+1);
auto itl=split(l);
t.erase(itl,itr);
t.insert({l,r,v});
return;
}
inline int ask(int l,int r,int v)
{
int cnt=0;
auto itr=split(r+1);
auto itl=split(l);
for(auto it=itl;it!=itr;it++)
{
if(it->v==v)
{
cnt+=it->r-it->l+1;
}
}
return cnt;
}
inline void sort(int l,int r)
{
int a[30];
memset(a,0,sizeof(a));
auto itr=split(r+1);
auto itl=split(l);
while(itl!=itr)
{
a[itl->v]+=itl->r-itl->l+1;
itl=t.erase(itl);
}
for(int i=1;i<=26;i++)
{
if(a[i])
{
t.insert({l,l+a[i]-1,i});
l+=a[i];
}
}
return;
}
int main()
{
n=read();m=read();
scanf("%s",c+1);
char last=toupper(c[1]);
c[1]=toupper(c[1]);
int cnt=1;
for(int i=2;i<=n;++i)
{
c[i]=toupper(c[i]);
if(c[i]==last)
{
++cnt;
}
else
{
t.insert({i-cnt,i-1,last-'A'+1});
last=c[i];
cnt=1;
}
}
t.insert({n+1-cnt,n,last-'A'+1});
t.insert({n+1,n+1,0});
while(m--)
{
int flag,l,r;
flag=read();l=read();r=read();
if(flag==1)
{
char k;
scanf(" %c",&k);
printf("%d\n",ask(l,r,toupper(k)-'A'+1));
}
else if(flag==2)
{
char k;
scanf(" %c",&k);
assign(l,r,toupper(k)-'A'+1);
}
else
{
sort(l,r);
}
}
return 0;
}