URAL - 1989 Subpalindromes 线段树哈希

题目链接:点击查看

题意:给一个串,两种操作,一个数查询区间是否为回文串,另一个是更改某一位置 的字符。

题解:哈希,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
*/

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89191172