首页 > 其他分享 >[ABC331F] Palindrome Query 题解

[ABC331F] Palindrome Query 题解

时间:2024-01-07 19:44:20浏览次数:22  
标签:ld Palindrome rs 题解 tr rd ls res Query

思路

判断一个字符串是否是回文串,可以从它的本质出发:正着读和倒着读是一样的。快速判断它正着和反着是否一样,用字符串哈希即可。又因为涉及单点修改,区间查询,那么使用线段树维护这两个值就行了。

这里讲一下如何 pushup。以正着的哈希值为例:我们要更新 \(p\) 这个点的 \(hash\) 值,已知 \(p\) 的左右儿子的哈希值 \(ls_{hash}\) 和 \(rs_{hash}\),那么按照正常的 \(hash\) 值更新右边的一坨式子应该要乘上一些 \(base\),乘多少呢?因为我们是以左边为起点,当更新到 \(rs\) 的左端点时左边已经乘了 \(ls.r-ls.l\) 个 \(base\),\(rs\) 的左端点就应该乘上 \(ls.r-ls.l+1\) 个 \(base\)。而 \(rs\) 内部的值是已经算好了的,所以整体乘上 \(ls.r-ls.l+1\) 个 \(base\) 就好了。也就是 \(base^{ls.r-ls.l+1}\)。

此题也就没什么难度了。小清新线段树。

code

#include<bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
using namespace std;
int n,q;
const int mod=998244353;
const ll base=47;
ll pw[1000005];
char s[1000005];
struct Tree{
	int l,r;
	ll lnum,rnum;
}tr[4000005];
void pushup(int p){
	tr[p].lnum=(tr[ls].lnum+(pw[tr[ls].r-tr[ls].l+1]*tr[rs].lnum)%mod)%mod;//更新hash值
	tr[p].rnum=(tr[rs].rnum+(pw[tr[rs].r-tr[rs].l+1]*tr[ls].rnum)%mod)%mod;
}
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	if(l==r){
		tr[p].lnum=tr[p].rnum=(ll)(s[l]-'a'+1);
		return;
	}
	int mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p);
}
void update(int p,int x,char c){
	if(tr[p].l==tr[p].r){
		tr[p].lnum=tr[p].rnum=(ll)(c-'a'+1);
		return;
	}
	int mid=tr[p].l+tr[p].r>>1;
	if(x<=mid)update(ls,x,c);
	else update(rs,x,c);
	pushup(p);
}
Tree query(int p,int l,int r){
	if(tr[p].l>=l&&tr[p].r<=r)return tr[p];
	int mid=tr[p].l+tr[p].r>>1;
	if(r<=mid)return query(ls,l,r);
	if(l>mid)return query(rs,l,r);
	Tree ld=query(ls,l,r),rd=query(rs,l,r);//合并两段的hash值
	Tree res;
	res.l=ld.l;res.r=rd.r;
	res.lnum=(ld.lnum+(pw[ld.r-ld.l+1]*rd.lnum)%mod)%mod;
	res.rnum=(rd.rnum+(pw[rd.r-rd.l+1]*ld.rnum)%mod)%mod;
	return res;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>q;
	cin>>(s+1);
	pw[0]=1;
	for(int i=1;i<=n;++i)pw[i]=(pw[i-1]*base)%mod;//预处理base的次幂
	build(1,1,n);
	while(q--){
		int op,l,r,x;
		char c;
		cin>>op;
		if(op==1){
			cin>>x>>c;
			update(1,x,c);
		}
		else{
			cin>>l>>r;
			Tree now=query(1,l,r);
			if(now.lnum==now.rnum)cout<<"Yes\n";//正着读倒着读相同
			else cout<<"No\n";
		}
	}
	return 0;
}

标签:ld,Palindrome,rs,题解,tr,rd,ls,res,Query
From: https://www.cnblogs.com/sunsetlake/p/17951066

相关文章

  • 1 月杂题题解
    好久没写博客了?今晚写爽。P5311成都七中这有黑?对于一个点\(x\),设其子树任意一点为\(y\)。我们可以求出这\(x\rightarrowy\)这条路径经过节点的的\(l,r\)。遍历\(x\)的子树,我们可以得到一些三元组\((l,r,c)\)表示\(x\)所属连通块包含了\(l,r\)这些节点,就有一......
  • [ABC273D] LRUD Instructions 题解
    [ABC273D]LRUDInstructions题解很好的一道大模拟,使我爆\(0\)。思路解析大模拟,我们只需要用一个\(x,y\)表示我们当前的位置,而对于每一个移动,我们就判断在当前移动方向上离当前点最近的点,若该点在当前行进路线上,则把当前位置设为该点前面的一个。其中判断在当前移动方向上......
  • CF1045G AI robots题解
    题目链接:洛谷或者CF本题考虑转化为cdq分治模型对于cdq分治来说,只需要考虑左边对右边的影响,那我们要考虑该怎样设置第一维度的左右对象。很显而易见的是抛开\(q\)限制而言,我们着眼于,如何让双方互相看到的严格条件转化为只需要关注单体看见。考虑什么情况下只需要一方看到......
  • nested exception is java.lang.IllegalArgumentException异常问题解决
    项目启动报错如下:nestedexceptionisjava.lang.IllegalArgumentException:Couldnotresolveplaceholder'xxx'invalue"${xxx}"问题解决比较简单,只说我所遇到的情况,原因就是字母拼写问题仔细看还是能看到大写的K和小写的k有一些细微的区别,将nacos中的k和代码中修改一致后启......
  • 奇迹服务端问题解答
    1.怎么修改IIS的连接限制10个啊暂时好像没有完善的修改软件,有是有,但是我试了几次都失败,就不推荐了2.怎么修改游戏中商店出售的物品啊DMuServerDataShop1.txt~Shop11.txt3.Terrain1.Att~Terrain35.Att这些有什么用啊这个是服务端地图...4.服务端的怪物太吊了怎么修改它们LS点啊DM......
  • JQuery 修改用户信息
    JQuery修改用户信息,多项选择,赋值,框架$(data.data.roleList).each(function(i,val){$('input[type="checkbox"][name="doctorRole"]').each(function(){if(this.value==val.roleCode){this.checked=true;}......
  • JQuery 获取URL参数
    JQuery获取URL参数,JS日期格式化,cookie不存在,跳登录页在jQuery中,可以使用window.location.search属性获取URL中的查询参数。该属性返回一个字符串,其中包含URL中的查询参数和对应的值。下面是一个简单的示例,展示如何使用jQuery获取URL中的参数......
  • [ABC271E] Subsequence Path 题解
    [ABC271E]SubsequencePath题解思路解析很好的一道题,很有迷惑性,表面上是一道图论实际上是dp,定义\(f_{i}\)为从\(1\)到\(i\)的最短“好路”。先把每条边对应的起点,终点和边权记录下来,然后输入每个\(e\),由于是子序列顺序不会改变,因此可以顺序进行操作。对于每一个\(e......
  • P2726 [SHOI2005] 树的双中心 题解
    Description\(n\leq5\times10^4\),树的深度\(\leq100\)。Solution对于每个\(x,y\),满足\(d(v,x)\leqd(v,y)\)或者\(d(v,x)\geqd(v,y)\)的点一定构成一个子树,所以可以枚举这个子树的根,然后对两边分别求重心可以得到答案。但是直接暴力求是\(O(n^2)\)的,过不了。注......
  • CF763E Timofey and our friends animals题解
    题目链接:CF或者洛谷简单来说就是求\([l,r]\)这些点都存在的情况下,连通块的数量,看到七秒时限,而且每个点相连的边数很少,可以想到离线下来使用莫队类的算法解决连通块问题,一般可以考虑使用并查集解决。对于并查集来说,它的增加是非常简单的,但删除是困难的,可持久化并查集时空常数......