目录
显示
题目链接
https://www.luogu.org/problem/P2787
题解
(大小写不敏感大草)
有区间推平操作,考虑用 珂朵莉树 来解决。
(看上去跑的还挺快的样子)
#include <cstdio>
#include <cstring>
#include <set>
#include <iterator>
#include <algorithm>
using namespace std;
struct node
{
int l,r,val;
node(int L,int R=-1,int Val=0)
{
l=L,r=R,val=Val;
}
bool operator<(const node&a)const
{
return l<a.l;
}
};
char s[50005];
set<node> se;
set<node>::iterator split(int pos)
{
auto it=se.lower_bound(pos);
if(it!=se.end()&&it->l==pos)return it;
it--;
int l=it->l,r=it->r,val=it->val;
se.erase(it);
se.insert(node(l,pos-1,val));
return se.insert(node(pos,r,val)).first;
}
void assign(int l,int r,int x)
{
auto itr=split(r+1),itl=split(l);
se.erase(itl,itr);
se.insert(node(l,r,x));
}
int query(int l,int r,int x)
{
auto itr=split(r+1),itl=split(l);
int ans=0;
for(auto it=itl;it!=itr;it++)
if(it->val==x)ans+=(it->r)-(it->l)+1;
return ans;
}
void strsort(int l,int r)
{
auto itr=split(r+1),itl=split(l);
static int t[35];
memset(t,0,sizeof(t));
for(auto it=itl;it!=itr;it++)
t[it->val]+=(it->r)-(it->l)+1;
se.erase(itl,itr);
int cur=l;
for(int i=0;i<26;i++)
if(t[i])
{
se.insert(node(cur,cur+t[i]-1,i));
cur+=t[i];
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
se.insert(node(i,i,s[i]-'a'>=0?s[i]-'a':s[i]-'A'));
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
scanf("%s",s);
printf("%d\n",query(x,y,s[0]-'a'>=0?s[0]-'a':s[0]-'A'));
}
else if(op==2)
{
scanf("%s",s);
assign(x,y,s[0]-'a'>=0?s[0]-'a':s[0]-'A');
}
else strsort(x,y);
}
return 0;
}