题目大意:给一行字符串,两种操作:change(pos,char),将pos处字符改为char;isPalindrome(i,j),询问[i,j]之间是否为回文字符串。

题目分析:做正反两次字符串哈希,如果哈希值一样则回文。用线段树维护哈希值,单点更新即可。

我的挫代码如下:

# include<cstdio>
# include<iostream>
# include<cstring>
# include<algorithm>
using namespace std;
# define mid (l+(r-l)/2) const int N=100000; int seed[2]={31,131};
unsigned int base[2][N+5]; char str[N+5];
char op[2];
unsigned int tr_left[2][N*4+5];
unsigned int tr_right[2][N*4+5]; struct Node{
unsigned int left[2];
unsigned int right[2];
}; inline void init()
{
for(int i=0;i<2;++i){
base[i][0]=1;
for(int j=1;j<=N;++j){
base[i][j]=base[i][j-1]*seed[i];
}
}
} inline void read(int &x)
{
x=0;
char c;
while((c=getchar())&&(c<'0'||c>'9'));
x=c-'0';
while(c=getchar()){
if(c<'0'||c>'9') break;
x=x*10+c-'0';
}
} inline bool ok(Node *a)
{
for(int i=0;i<2;++i)
if(a->left[i]!=a->right[i]) return false;
return true;
} inline void pushUp(int rt,int l,int r)
{
for(int i=0;i<2;++i){
tr_left[i][rt]=tr_left[i][rt<<1]*base[i][r-mid]+tr_left[i][rt<<1|1];
tr_right[i][rt]=tr_right[i][rt<<1|1]*base[i][mid-l+1]+tr_right[i][rt<<1];
}
} inline void build(int rt,int l,int r)
{
if(l==r){
for(int i=0;i<2;++i)
tr_left[i][rt]=tr_right[i][rt]=str[l]-'a'+1;
}else{
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushUp(rt,l,r);
}
} inline void update(int rt,int l,int r,int x,char c)
{
if(l==r){
for(int i=0;i<2;++i)
tr_left[i][rt]=tr_right[i][rt]=c-'a'+1;
}else{
if(x<=mid) update(rt<<1,l,mid,x,c);
else update(rt<<1|1,mid+1,r,x,c);
pushUp(rt,l,r);
}
} inline Node* query(int rt,int l,int r,int L,int R)
{
Node* nde=new Node;
if(L<=l&&r<=R){
for(int i=0;i<2;++i){
nde->left[i]=tr_left[i][rt];
nde->right[i]=tr_right[i][rt];
}
}else{
Node* nde1=NULL;
Node* nde2=NULL;
if(L<=mid) nde1=query(rt<<1,l,mid,L,min(R,mid));
if(R>mid) nde2=query(rt<<1|1,mid+1,r,max(mid+1,L),R);
if(nde1!=NULL&&nde2!=NULL){
for(int i=0;i<2;++i){
nde->left[i]=nde1->left[i]*base[i][R-mid]+nde2->left[i];
nde->right[i]=nde2->right[i]*base[i][mid-L+1]+nde1->right[i];
}
}else{
if(nde1!=NULL){
for(int i=0;i<2;++i){
nde->left[i]=nde1->left[i];
nde->right[i]=nde1->right[i];
}
}else if(nde2!=NULL){
for(int i=0;i<2;++i){
nde->left[i]=nde2->left[i];
nde->right[i]=nde2->right[i];
}
}
}
if(nde1!=NULL) delete nde1;
if(nde2!=NULL) delete nde2;
}
return nde;
} int main()
{
init();
int m;
while(~scanf("%s",str))
{
int n=strlen(str);
build(1,0,n-1);
scanf("%d",&m);
int a,b;
char ch[2];
while(m--)
{
scanf("%s",op);
if(op[0]=='p'){
read(a);
read(b);
Node *nde=query(1,0,n-1,a-1,b-1);
if(ok(nde)) printf("Yes\n");
else printf("No\n");
delete nde;
}else if(op[0]=='c'){
read(a);
scanf("%s",ch);
update(1,0,n-1,a-1,ch[0]);
}
}
}
return 0;
}

  

URAL-1989 Subpalindromes(单点更新+hash)的更多相关文章

  1. URAL 1989 Subpalindromes (多项式hash) +【线段树】

    <题目链接> <转载于 >>>  > 题目大意:给你一段字符串,进行两种操作:1.询问[l,r]这个区间中的字符串是否是回文串: 2.更改该字符串中对应下标的 ...

  2. N - Subpalindromes URAL - 1989 哈希+线段树

    N - Subpalindromes URAL - 1989 这个是一个哈希+线段树,这个题目也不算特别难,但是呢,还比较有意思. 这个题目给你两个操作,一个是回答l~r 区间是不是回文,一个是对一个 ...

  3. ural1989 单点更新+字符串hash

    正解是双哈希,不过一次哈希也能解决.. 然后某个数字就对应一个字符串,虽然有些不同串对应同一个数字,但是概率非常小,可以忽略不计.从左到右.从右到左进行两次hash,如果是回文串,那么对应的整数必定存 ...

  4. 单点更新线段树 RMQ

    D. Xenia and Bit Operations time limit per test 2 seconds memory limit per test 256 megabytes input ...

  5. ural 1989 subplindromes

    https://vjudge.net/problem/URAL-1989 题意: 先给出一个字符串,对于这个字符串,有两种操作,一种是询问从下标x到y的串是不是回文串,另一种是将下标为pos的字符改为 ...

  6. HDU 1754 I Hate It 线段树单点更新求最大值

    题目链接 线段树入门题,线段树单点更新求最大值问题. #include <iostream> #include <cstdio> #include <cmath> ...

  7. HDU 1166 敌兵布阵 线段树单点更新求和

    题目链接 中文题,线段树入门题,单点更新求和,建一棵树就可以了. #include <iostream> #include <cstdio> #include <cmat ...

  8. HDU 1166 敌兵布阵(线段树单点更新)

    敌兵布阵 单点更新和区间更新还是有一些区别的,应该注意! [题目链接]敌兵布阵 [题目类型]线段树单点更新 &题意: 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N< ...

  9. UVA 12299 RMQ with Shifts(线段树:单点更新)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

随机推荐

  1. K2 BPM + SAP,实现全方面管理企业

    K2作为专业的BPM.工作流管理平台供应商,面向庞大的SAP用户群体,除了提供产品化的SAP集成工具「K2 connect」产品之外,更拥有一套得到众多客户验证的集成解决方案. 此方案可供SAP用户或 ...

  2. JAVA每日一记

    1.两个最基本的java回收算法:复制算法和标记清理算法                 复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B.此为新生代最常用的算法            ...

  3. grub2的使用

    1,添加win 启动项 edit file: /boot/grub2/grub.cfg 插入这几行: menuentry 'Windows XXX' { set root=(hd0,) chainlo ...

  4. oracle触发器如何使用2

    触发器 是特定事件出现的时候,自动执行的代码块.类似于存储过程,但是用户不能直接调用他们.触发器是许多关系数据库系统都提供的一项技术.在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处 ...

  5. Spring中@Resource、@controller注解的含义

    @Resource 注解被用来激活一个命名资源(named resource)的依赖注入,在JavaEE应用程序中,该注解被典型地转换为绑定于JNDI context中的一个对象. Spring确实支 ...

  6. IOS @2X.png

    [UIImage imageNamed:@"xxx.png"] 或者xib里iPhone4会自动找*@2x.png initWithContentOfFile:pathToImag ...

  7. Java容器类List,ArrayList及LinkedList

    List容器类图 List是一个接口,它继承自Collection和Iterable,它的实现类有AbstractList,AbstrackSequenceList,ArrayList,LinkedL ...

  8. python 优雅的使用正则表达式 ~ 2

    使用正则表达式 那些基础的理论也说了不少了现在就开始 实操 ( 不知道为啥特别喜欢这个词... ) 吧 . 上一节课说过 正则表达式也是一门语言 , 他被集成到了python当中 , 并且用 re 模 ...

  9. Java 集合深入理解(3):Collection

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情有点粉,来学学 Collection 吧! 什么是集合? 集合,或者叫容器,是一个包含多个元素的对象: 集合可以对 ...

  10. dat文件中如何编写DOS的多行命令

    dat文件中如何编写DOS的多行命令 2012-10-15 11:29 四海柔情108 分享到:   2012-10-16 23:36 提问者采纳   你问的应该是BAT文件吧?BAT是DOS命令的批 ...