AT_abc331_f [ABC331F] Palindrome Query 题解
分析
线段树。
每个节点维护两个值:
首先想到用线段树暴力维护。第一个值很显然是两个儿子的第一个值加起来,第二个值是反着加起来。得到很酷的代码:
il void up(int now){
tr[now].ls=tr[now<<1].ls+tr[now<<1|1].ls,
tr[now].rs=tr[now<<1|1].rs+tr[now<<1].rs;
return ;
}
il void build(int now,int l,int r){
tr[now].l=l,tr[now].r=r;
if(l==r) tr[now].ls=tr[now].rs=s[l-1];
else build(now<<1,l,(l+r)>>1),build(now<<1|1,((l+r)>>1)+1,r),up(now);
return ;
}
il void insert(int now,int k,int c){
if(tr[now].l==tr[now].r){tr[now].ls=tr[now].rs=c;}
else{
int mid=tr[now].l+tr[now].r>>1;
if(k<=mid) insert(now<<1,k,c);
else insert(now<<1|1,k,c);
up(now);
}
return ;
}
il tree query(int now,int l,int r){
tree ans={0,0,"",""};
if(tr[now].l>=l&&tr[now].r<=r) return tr[now];
int mid=tr[now].l+tr[now].r>>1;
if(l<=mid) ans=query(now<<1,l,r);
if(mid<r){
tree ans1=query(now<<1|1,l,r);
ans.ls=ans.ls+ans1.ls,ans.rs=ans1.rs+ans.rs;
}
return ans;
}
然后就 TLE 了。原因是两个字符串相加复杂度太高。
考虑把字符串转化成数字。在字符串哈希中,第
然后就没了。改变上传的价值。定义那时候的
询问的时候在节点右端点包含询问区间右端点时注意一下左右限制即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register
#define il inline
const int N=1e6+10,p=1e9+7;
int n,q;
string s;
int b[N],bk=190;
struct tree{
int l,r;
int ls,rs;
}tr[N<<2];
il void up(int now){
int mid=tr[now].l+tr[now].r>>1;
tr[now].ls=(tr[now<<1].ls*b[tr[now].r-mid]%p+tr[now<<1|1].ls)%p,
tr[now].rs=(tr[now<<1|1].rs*b[mid-tr[now].l+1]%p+tr[now<<1].rs)%p;
return ;
}
il void build(int now,int l,int r){
tr[now].l=l,tr[now].r=r;
if(l==r) tr[now].ls=tr[now].rs=(s[l-1]+1-'a');
else build(now<<1,l,(l+r)>>1),build(now<<1|1,((l+r)>>1)+1,r),up(now);
return ;
}
il void insert(int now,int k,int c){
if(tr[now].l==tr[now].r){tr[now].ls=tr[now].rs=c;}
else{
int mid=tr[now].l+tr[now].r>>1;
if(k<=mid) insert(now<<1,k,c);
else insert(now<<1|1,k,c);
up(now);
}
return ;
}
il tree query(int now,int l,int r){
tree ans={0,0,0,0};
if(tr[now].l>=l&&tr[now].r<=r) return tr[now];
int mid=tr[now].l+tr[now].r>>1;
if(l<=mid) ans=query(now<<1,l,r);
if(mid<r){
tree ans1=query(now<<1|1,l,r);
if(l<=mid)
ans.ls=(ans.ls*b[min(r,tr[now].r)-mid]%p+ans1.ls)%p,
ans.rs=(ans1.rs*b[mid-max(tr[now].l,l)+1]%p+ans.rs)%p;
else ans=ans1;
}
return ans;
}
il void solve(){
cin>>n>>q>>s;
b[0]=1;for(re int i=1;i<=n;++i) b[i]=b[i-1]*bk%p;
build(1,1,n);
for(re int i=1;i<=q;++i){
int op;cin>>op;
if(op==1){
int k;char c;cin>>k>>c;
insert(1,k,c+1-'a');
}
else{
int l,r;cin>>l>>r;
tree ans=query(1,l,r);
if(ans.ls==ans.rs) cout<<"Yes\n";
else cout<<"No\n";
}
}
return ;
}
signed main(){
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!