#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N=1e6+10,INF=0x3f3f3f3f,base=131;
int read() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();return x*f;}
void Write(int x) {if(x<0) {putchar('-'),Write(-x);return;}if(x<10) {putchar(x+'0');return;}Write(x/10),putchar(x%10+'0');}
void write(int x,char *s) {Write(x),printf("%s",s);}
int n,m;ull pw[N];
string s;
namespace SGT
{
#define ls (id<<1)
#define rs (id<<1|1)
#define mid (l+r>>1)
int len[N<<2];ull hshL[N<<2],hshR[N<<2];
void push_up(int id) {hshL[id]=hshL[ls]+hshL[rs]*pw[len[ls]],hshR[id]=hshR[ls]*pw[len[rs]]+hshR[rs];}
void build(int id,int l,int r)
{
if(l==r) {len[id]=1,hshL[id]=hshR[id]=s[l];return;}
build(ls,l,mid),build(rs,mid+1,r),len[id]=len[ls]+len[rs],push_up(id);
}
void update(int id,int l,int r,int x,char ch)
{
if(l==r) {hshL[id]=hshR[id]=ch;return;}
if(x<=mid) update(ls,l,mid,x,ch);
else update(rs,mid+1,r,x,ch);
push_up(id);
}
ull queryL(int id,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return hshL[id];
if(L<=mid&&R>mid) return queryL(ls,l,mid,L,R)+queryL(rs,mid+1,r,L,R)*pw[mid-L+1];
else if(L<=mid) return queryL(ls,l,mid,L,R);
else return queryL(rs,mid+1,r,L,R);
}
ull queryR(int id,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return hshR[id];
if(L<=mid&&R>mid) return queryR(ls,l,mid,L,R)*pw[R-mid]+queryR(rs,mid+1,r,L,R);
else if(L<=mid) return queryR(ls,l,mid,L,R);
else return queryR(rs,mid+1,r,L,R);
}
}using namespace SGT;
void solve()
{
n=read(),m=read(),cin>>s,s=" "+s,pw[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base;
build(1,1,n);
for(int i=1,op,x,y;m--;)
{
op=read(),x=read();char ch;
if(op==1) scanf(" %c",&ch),update(1,1,n,x,ch);
else y=read(),puts(queryL(1,1,n,x,y)==queryR(1,1,n,x,y)?"Yes":"No");
}
}
signed main()
{
int T=1;
while(T--) solve();
}
思路是维护区间左到右和右到左的hash,但是WA*13。改成双哈希也一样