URAL 1989 Subpalindromes（回文串 线段树 多项式hash）

1989. Subpalindromes

Time limit: 0.5 second
Memory limit: 64 MB
You have a string and queries of two types:
1. replace i’th character of the string by character a;
2. check if substring sj...sk is a palindrome.

Input

The first line contains a string consisting of n small English letters.The second line contains an integer m that is the number of queries(5 ≤n, m ≤ 105). The next m lines contain the queries.
Each query has either form “change i a”, or “palindrome? j k”, where i, j, k are integers (1 ≤ in; 1 ≤ j kn), and character a is a small English letter.

Output

To all second type queries, you should output “Yes” on a single line if substringsj...sk is a palindrome and “No” otherwise.

Sample

input output
abcda
5
palindrome? 1 5
palindrome? 1 1
change 4 b
palindrome? 1 5
palindrome? 2 4

No
Yes
Yes
Yes

Problem Author: Mikhail Rubinchik
Problem Source: Open Ural FU Championship 2013

KeyL=str[ L] +str[L+1]*K  + str[L+2]* K^2  +...str[R] * K^(R-L)

KeyR=str[R] +str[R-1]*K  + str[R-2]* K^2  +...str[L] * K^(R-L)

/*=============================================================================
#
#      Author: liangshu - cbam
#
#      QQ : 756029571
#
#      School : 哈尔滨理工大学
#
#
#     Filename: A.cpp
#
#     Description:
#        The people who are crazy enough to think they can change the world, are the ones who do !
=============================================================================*/
#

#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cctype>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;

#define lson l, m, rt<<1
#define rson m + 1, r, rt<<1|1
const int k = 137;
const int maxn  = 100003;
char str1[maxn];
int Pow[maxn];
int str2[maxn];
int N, M;
struct Node{
int keyL,keyR;
Node():keyL(0), keyR(0){}
Node(int x, int y):keyL(x), keyR(y){}
}node[maxn<<2];

void init(){
for(int i = 1;i <= maxn<<2; i++){
node[i].keyL = node[i].keyR = 0;
}
}

void pushup(int L ,int R, int rt){
node[rt].keyL = node[rt<<1].keyL + node[rt<<1|1].keyL*Pow[L];
node[rt].keyR = node[rt<<1].keyR * Pow[R] + node[rt<<1|1].keyR;
}

void build (int l, int r, int rt){
if(l == r){
node[rt].keyL = node[rt].keyR = str2[l];return ;
}
int m = (l + r)>>1;
build(lson);
build(rson);
pushup(m - l + 1, r - m , rt);
}

void update(int p, int val, int l, int r, int rt){
if( l == r){
node[rt].keyL = node[rt].keyR = val;return ;
}
int m = ( l + r )>>1;
if(p <= m)update(p, val, lson);
else update( p, val, rson );
pushup(m - l + 1, r - m, rt);
}

Node query(int L, int R, int l, int r,int rt){
if(L <= l && r <= R){

return node[rt];
}
Node ans, ans1, ans2;
int T = 0;
int m = (l + r)>>1;
if(L <= m)ans1 = query(L, R, lson),T += 1;
if(R > m) ans2 = query(L, R, rson),T += 2;

if( T == 1 )ans = ans1;
else if(T == 2)ans = ans2;
else if(T == 3){
ans.keyL = ans1.keyL + ans2.keyL * Pow[m -max(L, l) + 1];
ans.keyR = ans1.keyR * Pow[min(R, r) - m] + ans2.keyR;
}
return ans;
}

int main(){

while(~scanf("%s", str1 + 1)){
int L = strlen(str1 + 1) ;
Pow[0] = 1;
for(int i = 1; i <= L; i++){
Pow[i] = Pow[i - 1] * k;
}
for(int i = 1; i <= L; i++){
str2[i] = str1[i] - 'a';
}
init();
scanf("%d", &M);
build(1, L, 1);
for(int i = 1; i <= M; i++){
char op[23];
scanf("%s",op);
if(op[0] == 'c'){
int a;char b;
scanf("%d %c",&a,  &b);
update(a, b - 'a', 1, L, 1);
}
else {
int a, b;
scanf("%d%d", &a, &b);
Node ans = query(a, b, 1, L, 1);
bool T = ans.keyL == ans.keyR;
if(T)printf("Yes\n");
else printf("No\n");
}
}
}
return 0;

}