#include using namespace std; #define sd(a) scanf("%d",&a) #define ss(a) scanf("%s",a) #define sl(a) scanf("%lld",&a) #define clr(a) memset(a,0,sizeof(a)) #define debug(a) printf("check%d\n",a) #define F first #define S second #define MP make_pair #define PB push_back #define ll long long #define N 100010 #define mod 1000000007 struct node { int c[26],l; node() { clr(c); } }t[4*N]; char s[N]; inline void merge(node &n,node &n1,node &n2) { for(int i=0;i<26;i++) n.c[i]=n1.c[i]+n2.c[i]; } void build_tree(int n,int si,int sj) { t[n].l=0; if(si==sj) { clr(t[n].c); t[n].c[s[si]-'a']=1; return; } build_tree(n*2,si,(si+sj)/2); build_tree(n*2+1,(si+sj)/2+1,sj); merge(t[n],t[n*2],t[n*2+1]); } inline void Rev(node &n,int st,int en) { for(int i=0;i<(en-st+1)/2;i++) swap(n.c[st+i],n.c[en-i]); } inline void Mod(int &x) { if(x>=26) x-=26; } inline void push(int n,int si,int sj) { if(!t[n].l) return; // cout<<"BEFORE: "; // for(int i=0;i<26;i++) // cout<en||sj=st&&sj<=en) { t[n].l+=val; Mod(t[n].l); if(t[n].l) push(n,si,sj); return; } update(n*2,si,(si+sj)/2,st,en,val); update(n*2+1,(si+sj)/2+1,sj,st,en,val); merge(t[n],t[n*2],t[n*2+1]); } node query(int n,int si,int sj,int st,int en) { node ret; if(t[n].l) push(n,si,sj); if(si>en||sj=st&&sj<=en) return t[n]; node n1=query(n*2,si,(si+sj)/2,st,en); node n2=query(n*2+1,(si+sj)/2+1,sj,st,en); merge(ret,n1,n2); return ret; } ll pow1(ll a,ll b) { if(b==0) return 1; ll ret=pow1(a,b/2); ret=(ret*ret)%mod; if(b&1) ret=(a*ret)%mod; return ret; } inline ll Even(int x) { return x/2+1; } int main() { int n,q,i; sd(n);sd(q); ss(s); build_tree(1,0,n-1); while(q--) { int ch,x,y,z; sd(ch); if(ch==1) { sd(x);sd(y);sd(z); z%=26; update(1,0,n-1,x,y,z); } else { sd(x);sd(y); node res=query(1,0,n-1,x,y); // for(i=0;i<26;i++) // cout<