De Prezer loves palindrome strings. A string s1s2...sn is palindrome if and only if it is equal to its reverse.

De Prezer also loves queries.

You are given string s of length n and m queries. There are 3 types of queries :

1. 1px : Modify sp = x where 1 ≤ p ≤ n and x is a lower case English letter.

2. 2p : Print the length of the largest palindrome substring of s like slsl + 1...sr such that l ≤ p ≤ r and r - p = p - l. (1 ≤ p ≤ n)

3. 3p : Print the length of the largest palindrome substring of s like slsl + 1...sr such that l ≤ p and p + 1 ≤ r and r - p - 1 = p - l. (1 ≤ p ≤ n - 1) or  - 1 if there is no such substring.

The first line of input contains s and m.

Next m lines contain queries.

1 ≤ n, m ≤ 105

s only contains lower case English letters.

For each query of type 2 and 3 print the answer in a single line.

解题报告:

大意就是给你一个字符串,有三种操作:

操作1:将某个位置的字符改成另外一个字符

操作2:询问以位置 x 为中点的奇回文串长度

操作3:询问以位置 x,x+1为中的偶回文串长度

我们建立一颗线段树来解决这个问题

线段树中的存储的 key1 表示 s[L] * p^0 +  S[L+1] * p ^1 + ..... S[R] * p ^ (R-L) , key2 值表示S[R] * p ^ 0 + S[R-1] * p ^1 + ...S[L] * p^(R-L)

显然key2 是倒着的,这样方便我们查询这个区间是否是回文子串

题目显然要求是单点更新,区间查询.

对于单点更新而言,最重要的就是push_up函数,我们考虑

将[L,mid] 和 [mid + 1 , R]进行合并时,注意到key值的含义,我们需要给右边的[mid+1,R]的key1值乘上p^(mid-L+1),key2则是给[L,mid]乘上p ^(R-mid+1)

那么更新我们就解决了,查询呢

下面皆以 key1 为例(key2同理可得)

对于key1而言,我们主要就是要给落在右边的查询区间段上的乘上一个值.

假设我们现在要查询的区间段是[ ql , qr ] ,此时所在的线段是[L,R],中点是mid , 我们假设 qr > mid(即有落在右边的部分)

那么我们需要给右边乘的值就是p ^ (mid - ql + 1) <仔细想想>

key2同理可得,这里不再累述

这样我们就解决了查询问题,那么对于每个询问,我们二分答案即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <iomanip>
#include <string>
#include <ctime>
typedef unsigned char byte;
#define pb push_back
#define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
#define local freopen("in.txt","r",stdin)
#define pi acos(-1) using namespace std;
typedef pair<unsigned int ,unsigned int> dl;
const int maxn = 1e5 + ;
const unsigned int p1 = ;
const unsigned int p2 = ;
unsigned int value1[maxn];
unsigned int value2[maxn]; typedef struct treenode
{
int l , r ;
dl key1,key2;
void updata(unsigned int v)
{
key1.first = key1.second = v;
key2.first = key2.second = v;
} }; treenode tree[maxn * ]; inline void build_tree(int o,int l,int r)
{
tree[o].l = l , tree[o].r = r , tree[o].key1.first = tree[o].key1.second = tree[o].key2.first = tree[o].key2.second = ;
if (r > l)
{
int mid = l + (r-l)/;
build_tree(*o,l,mid);
build_tree(*o+,mid+,r);
}
} inline void push_up(int o)
{
int ac = tree[*o].r - tree[*o].l + ;
int ac2 = tree[*o+].r - tree[*o+].l + ;
tree[o].key1.first = tree[*o].key1.first + tree[*o+].key1.first * value1[ac];
tree[o].key1.second = tree[*o].key1.second + tree[*o+].key1.second * value2[ac];
tree[o].key2.first = tree[*o].key2.first * value1[ac2] + tree[*o+].key2.first;
tree[o].key2.second = tree[*o].key2.second * value2[ac2] + tree[*o+].key2.second;
} void updata(int ql,int qr,int o,unsigned int v)
{
int l = tree[o].l , r = tree[o].r;
if (ql <= l && qr >= r)
tree[o].updata(v);
else
{
int mid = l + (r-l) / ;
if (mid >= ql)
updata(ql,qr,*o,v);
if (mid < qr)
updata(ql,qr,*o+,v);
push_up(o);
}
} dl query(int ql,int qr,int o,int type)
{
int l = tree[o].l , r = tree[o].r;
//cout << "L is " << l << " R is " << r << " ql is " << ql << " qr is " << qr << endl;
if (ql == l && qr == r)
{
if (type == ) return tree[o].key1;
else return tree[o].key2;
}
else
{
int mid = l + (r-l) / , ac;
dl res(,) , temp;
if (mid >= ql)
{
int atr = min(mid,qr);
temp = query(ql,atr,*o,type);
if (type == && qr - mid > )
{
temp.first *= value1[qr - mid];
temp.second *= value2[qr - mid];
}
res.first += temp.first;
res.second += temp.second;
}
if (mid < qr)
{
int ltr = max(ql,mid+);
temp = query(ltr,qr,*o+,type);
if (type == && mid - ql + > )
{
temp.first *= value1[mid - ql + ];
temp.second *= value2[mid - ql + ];
}
res.first += temp.first;
res.second += temp.second;
}
//cout << "L is " << l << " R is " << r << " fist-value is " << res.first << " second-value is " << res.second << endl;
return res;
}
} char str[maxn] , temp[];
int length , m ; bool equaldl(dl x,dl y)
{
return x.first == y.first && x.second == y.second;
} int main(int argc,char *argv[])
{
scanf("%s%d",str,&m);
value1[] = value2[] = ;
length = strlen(str);
build_tree(,,length-);
for(int i = ; i <= length ; ++ i)
{
value1[i] = value1[i-]*p1;
value2[i] = value2[i-]*p2;
}
for(int i = ; i < length ; ++ i) updata(i,i,,(unsigned int)str[i]);
while(m--)
{
int type,x;
scanf("%d",&type);
if (type == )
{
scanf("%d%s",&x,temp);
x--;
str[x] = temp[];
updata(x,x,,temp[]);
}
else
{
scanf("%d",&x);
int L , R;
x--;
if (type == )
{
L = , R = min( x + , length - x );
while(L < R)
{
int mid = L + (R-L+) / ;
int tl = x - mid + ;
int tr = x + mid - ;
if (equaldl(query(tl,tr,,),query(tl,tr,,))) L = mid;
else R = mid - ;
}
printf("%d\n",*L-);
}
else
{
if (x+ >= length || str[x] != str[x+]) printf("-1\n");
else
{
int L = , R = min(x + , length - x - );
while(L < R)
{
int mid = L + (R-L+) / ;
int tl = x - mid + ;
int tr = x + mid;
if (equaldl(query(tl,tr,,),query(tl,tr,,))) L = mid;
else R = mid - ;
}
printf("%d\n",*L);
}
}
}
}
return ;
}

Gym 100570E : Palindrome Query的更多相关文章

  1. Codeforces Gym 100570 E. Palindrome Query Manacher

    E. Palindrome QueryTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100570/pro ...

  2. Gym - 100570E:Palindrome Query (hash+BIT+二分维护回文串长度)

    题意:给定字符串char[],以及Q个操作,操作有三种: 1:pos,chr:把pos位置的字符改为chr 2:pos:问以pos为中心的回文串长度为多长. 3:pos:问以pos,pos+1为中心的 ...

  3. codeforce Gym 100570B ShortestPath Query (最短路SPFA)

    题意:询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同,无重边且边权为正. 题解:因为路径的合法性和边的颜色有关, 所以在做spfa的时候,把边丢到队列中去,松弛的时候注意判断一下颜 ...

  4. Gym - 100676F Palindrome —— 并查集

    题目链接:https://vjudge.net/contest/155789#problem/E 题解: 由于是回文串,所以可以先将在对称位置的字符放在同一个集合(如果期间有两个非‘?’,且不相等,则 ...

  5. Solution -「Gym 102759I」Query On A Tree 17

    \(\mathcal{Description}\)   Link.   给定一棵含 \(n\) 个结点的树,结点 \(1\) 为根,点 \(u\) 初始有点权 \(a_u=0\),维护 \(q\) 次 ...

  6. Codeforces Gym 100571A A. Cursed Query 离线

    A. Cursed QueryTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100571/problem ...

  7. Gym 100952H&&2015 HIAST Collegiate Programming Contest H. Special Palindrome【dp预处理+矩阵快速幂/打表解法】

    H. Special Palindrome time limit per test:1 second memory limit per test:64 megabytes input:standard ...

  8. Gym 100952C&&2015 HIAST Collegiate Programming Contest C. Palindrome Again !!【字符串,模拟】

    C. Palindrome Again !! time limit per test:1 second memory limit per test:64 megabytes input:standar ...

  9. Gym 100952 H. Special Palindrome

    http://codeforces.com/gym/100952/problem/H H. Special Palindrome time limit per test 1 second memory ...

随机推荐

  1. vim编辑器的设置文件

    vim配置特点: 1.按F5可以直接编译并执行C.C++.java代码以及执行shell脚本,按“F8”可进行C.C++代码的调试 2.自动插入文件头 ,新建C.C++源文件时自动插入表头:包括文件名 ...

  2. FreeBSd ports 安装软件

    1.ports的目录在/usr/ports2.POSTS安装软件有时可能这个包已经安装过了,会有提示,无法 继续安装.能够用提示中的参数:#make install clean FORCE_PKG_R ...

  3. URAL 1658

    题目大意:求出T个最小的满足各个位的和为S1,平方和为S2的数.按顺序输出.数的位数大于100或者不存在这样一个数时,输出:No solution. KB     64bit IO Format:%I ...

  4. c语言验证哥德巴赫猜想(从4开始 一个偶数由两个质数之和)

    #include <stdio.h> #include <stdlib.h> #include <math.h> int isit(int num) { int i ...

  5. Adroid APPIUM实例步骤

      1.下载eclipse 2.安装java 配置环境变量 3.eclipse 安装adt android development tools 4.android sdk manager 安装tool ...

  6. 分享一个option样式传递给select当前选中样式

    今天遇到一个很是纠结的问题,需求又改了!原生的select给option加样式,结果发现select选中仍是默认样式,如下图:

  7. Wikioi 1080一维树状数组

    半个月时间最终把那些杂七杂八的学完了,尽管学完也,也仅仅是有了个模板,自己手敲还是不太行.所以如今開始要疯狂刷题了! ! .!!! 这题裸的树状数组.曾经写那道<敌兵布阵>的时候写过,所以 ...

  8. hdu1978How many ways (记忆化搜索+DFS)

    Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 1.机器人一开始在棋盘的起始点并有起始点所标 ...

  9. Hacker(20)----手动修复Windows系统漏洞

    Win7系统中存在漏洞时,用户需要采用各种办法来修复系统中存在的漏洞,既可以使用Windows Update修复,也可使用360安全卫士来修复. 一.使用Windows Update修复系统漏洞 Wi ...

  10. 使用xdebug+eclipse远程调试centOS7上的PHP代码

    这两天一直在研究PHP代码的调试,原来开发一直用的var_dump,麻烦! 最近发现能使用xdebug+eclipse远程单步调试PHP,但是百度后实现此技术的文章都写得不够具体. 我照着这里零散的文 ...