题目链接:点击查看
题意:给一个串,两种操作,一个数查询区间是否为回文串,另一个是更改某一位置 的字符。
题解:哈希,hash[i] = hash[i-1] * p,p我们可以设为27,剩下的就是直接区间合并即可,原以为思路不对,打了20分钟表,终于找到哪里错了,要注意的是几个数相乘,结果溢出,乘的循序不同,结果是相同的。
两种写法,一、直接确定一个区间的是多少,二每个位置都根据首部确定值,最后再判断一下左右两串的初始位置即可
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int mod=1610612741;
const int N=1e5+10;
struct node{
int l,r,le;
ll val;
}t[2][N<<2];
char s[N];
int len,n;
ll f[N];
void init()
{
f[1]=27;
for(int i=2;i<=100000;i++)
f[i]=f[i-1]*27;
}
void pushup(int id,int cur)
{
if(!id)t[id][cur].val=(t[id][cur<<1].val*f[t[id][cur<<1|1].le]+t[id][cur<<1|1].val);
if(id) t[id][cur].val=(t[id][cur<<1].val+t[id][cur<<1|1].val*f[t[id][cur<<1].le]);
}
void build(int id,int l,int r,int cur)
{
t[id][cur].l=l;
t[id][cur].r=r;
t[id][cur].le=r-l+1;
if(l==r)
{
t[id][cur].val=(s[l]-'a'+1);
return;
}
int mid=(r+l)>>1;
build(id,l,mid,cur<<1);
build(id,mid+1,r,cur<<1|1);
pushup(id,cur);
// cout<<l<<" "<<r<<" "<<t[id][cur].val<<endl;
// cout<<l<<" "<<r<<" "<<t[0][cur].val<<" "<<t[1][cur].val<<endl;;
}
void update(int pos,int cur,char op)
{
if(t[0][cur].l==t[0][cur].r)
{
t[0][cur].val=op-'a'+1;
t[1][cur].val=op-'a'+1;
return;
}
if(pos<=t[0][cur<<1].r) update(pos,cur<<1,op);
else update(pos,cur<<1|1,op);
pushup(0,cur);
pushup(1,cur);
// cout<<l<<" "<<r<<" "<<t[0][cur].val<<" "<<t[1][cur].val
}
ll query(int id,int pl,int pr,int cur)
{
if(pl<=t[id][cur].l&&t[id][cur].r<=pr)
{
return t[id][cur].val;
}
ll res=0;
int mid=(t[id][cur].l+t[id][cur].r)>>1;
if(!id)
{
if(pr<=mid) res=query(id,pl,pr,cur<<1);
else if(pl>mid) res=query(id,pl,pr,cur<<1|1);
else
{
//下面的min注意
res=(query(id,pl,pr,cur<<1)*f[min(pr,t[id][cur].r)-mid]+query(id,pl,pr,cur<<1|1));
}
}
else
{
if(pr<=mid) res=query(id,pl,pr,cur<<1);
else if(pl>mid) res=query(id,pl,pr,cur<<1|1);
else
{
/ 下面的max注意
res=query(id,pl,pr,cur<<1)+query(id,pl,pr,cur<<1|1)*f[mid-max(pl,t[id][cur].l)+1];
}
}
// cout<<id<<" "<<max(pl,t[id][cur].l)<<" "<<min(pr,t[id][cur].r)<<" "<<res<<endl;
return res;
}
int main()
{
init();
while(~scanf("%s",s+1))
{
len=strlen(s+1);
build(0,1,len,1);
build(1,1,len,1);
int q;
char op[20];
int l,r,id;
char c[2];
scanf("%d",&q);
while(q--)
{
scanf("%s",op);
if(op[0]=='p')
{
scanf("%d%d",&l,&r);
if(l==r) printf("Yes\n");
else
{
ll ans1,ans2;
ans1=query(0,l,l+(r-l+1)/2-1,1);
ans2=query(1,r-(r-l+1)/2+1,r,1);
// cout<<ans1<<" "<<ans2<<" "<<l<<" "<<l+(r-l+1)/2-1<<" "<<r-(r-l+1)/2+1<<" "<<r<<endl;
printf(ans1==ans2?"Yes\n":"No\n");
}
}
else
{
scanf("%d%s",&l,op);
update(l,1,op[0]);
}
}
}
return 0;
}
/*
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
10
paa 1 10
paa 1 20
paa 1 30
paa 1 50
paa 5 5
paa 25 25
paa 24 40
*/
二、
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1610612741;
const int N=1e5+10;
struct node{
int l,r,le;
ll val;
}t[2][N<<2];
char s[N];
int len,n;
ll f[N];
void init()
{
f[0]=1;
f[1]=27;
for(int i=2;i<=100000;i++)
{
f[i]=f[i-1]*27;
}
}
void pushup(int id,int cur)
{
t[id][cur].val=t[id][cur<<1].val+t[id][cur<<1|1].val;
t[id][cur].val=t[id][cur<<1].val+t[id][cur<<1|1].val;
}
void build(int id,int l,int r,int cur)
{
t[id][cur].l=l;
t[id][cur].r=r;
t[id][cur].le=r-l+1;
if(l==r)
{
if(!id)t[id][cur].val=(s[l]-'a'+1)*f[l-1];
else t[id][cur].val=(s[l]-'a'+1)*f[len-l];
return;
}
int mid=(r+l)>>1;
build(id,l,mid,cur<<1);
build(id,mid+1,r,cur<<1|1);
pushup(id,cur);
// cout<<l<<" "<<r<<" "<<t[id][cur].val<<endl;
}
void update(int pos,int cur,char op)
{
if(t[0][cur].l==t[0][cur].r)
{
t[0][cur].val=(op-'a'+1)*f[pos-1];
t[1][cur].val=(op-'a'+1)*f[len-pos];
// cout<<t[1][cur].val<<" "<<len-pos<<endl;
return;
}
if(pos<=t[0][cur<<1].r) update(pos,cur<<1,op);
else update(pos,cur<<1|1,op);
pushup(0,cur);
pushup(1,cur);
// cout<<t[1][cur].l<<" "<<t[1][cur].r<<" "<<t[1][cur].val<<" * "<<t[0][cur].val<<endl;
}
ll query(int id,int pl,int pr,int cur)
{
if(pl<=t[id][cur].l&&t[id][cur].r<=pr)
return t[id][cur].val;
ll res=0;
int mid=(t[id][cur].l+t[id][cur].r)>>1;
if(!id)
{
if(pr<=mid) return query(id,pl,pr,cur<<1);
else if(pl>mid) return query(id,pl,pr,cur<<1|1);
else return (query(id,pl,pr,cur<<1)+query(id,pl,pr,cur<<1|1));
}
else
{
if(pr<=mid) return query(id,pl,pr,cur<<1);
else if(pl>mid) return query(id,pl,pr,cur<<1|1);
else return query(id,pl,pr,cur<<1)+query(id,pl,pr,cur<<1|1);
}
}
int main()
{
init();
while(~scanf("%s",s+1))
{
len=strlen(s+1);
build(0,1,len,1);
build(1,1,len,1);
int q;
char op[20];
int l,r;
char c[2];
scanf("%d",&q);
while(q--)
{
scanf("%s",op);
if(op[0]=='p')
{
scanf("%d%d",&l,&r);
if(l==r) printf("Yes\n");
else
{
ll ans1,ans2;
ans1=query(0,l,l+(r-l+1)/2-1,1);
ans2=query(1,r-(r-l+1)/2+1,r,1);
//
if(l-1 > len-r) ans2*=f[l-1 - (len-r)];
else ans1 *= f[(len-r)-(l-1)];
// cout<<ans1<<" "<<ans2<<" "<<l<<" "<<l+(r-l+1)/2-1<<" "<<r-(r-l+1)/2+1<<" "<<r<<endl;
printf(ans1==ans2?"Yes\n":"No\n");
}
}
else
{
scanf("%d%s",&l,op);
update(l,1,op[0]);
}
}
}
return 0;
}
/*
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
10
paa 1 10
paa 1 20
paa 1 30
paa 1 50
*/