Gym 100570E : Palindrome Query
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的更多相关文章
- Codeforces Gym 100570 E. Palindrome Query Manacher
E. Palindrome QueryTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100570/pro ...
- Gym - 100570E:Palindrome Query (hash+BIT+二分维护回文串长度)
题意:给定字符串char[],以及Q个操作,操作有三种: 1:pos,chr:把pos位置的字符改为chr 2:pos:问以pos为中心的回文串长度为多长. 3:pos:问以pos,pos+1为中心的 ...
- codeforce Gym 100570B ShortestPath Query (最短路SPFA)
题意:询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同,无重边且边权为正. 题解:因为路径的合法性和边的颜色有关, 所以在做spfa的时候,把边丢到队列中去,松弛的时候注意判断一下颜 ...
- Gym - 100676F Palindrome —— 并查集
题目链接:https://vjudge.net/contest/155789#problem/E 题解: 由于是回文串,所以可以先将在对称位置的字符放在同一个集合(如果期间有两个非‘?’,且不相等,则 ...
- Solution -「Gym 102759I」Query On A Tree 17
\(\mathcal{Description}\) Link. 给定一棵含 \(n\) 个结点的树,结点 \(1\) 为根,点 \(u\) 初始有点权 \(a_u=0\),维护 \(q\) 次 ...
- Codeforces Gym 100571A A. Cursed Query 离线
A. Cursed QueryTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100571/problem ...
- 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 ...
- 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 ...
- Gym 100952 H. Special Palindrome
http://codeforces.com/gym/100952/problem/H H. Special Palindrome time limit per test 1 second memory ...
随机推荐
- 【案例】舒邑:一个女装品牌的奇葩打法-@i黑马
[案例]舒邑:一个女装品牌的奇葩打法-@i黑马 [案例]舒邑:一个女装品牌的奇葩打法
- c语言中break continue goto return和exit的区别 联系(筛选奇数和goto求和)
break 一般你是用于循环和switch语句中,执行break,退出循环,如果是多层循环,那么退出的当前的循环. 如果循环结构中有switch语句,而switch语句中有break 那么不会直接退出 ...
- Spring MVC + Spring MongoDB + Querydsl 通过maven整合实例
效果图 一共3个页面:注册页,欢迎页,用户列表页 很简单的例子,主要是为了把流程走通,没有各种验证. 注册页: 欢迎页: 用户列表页: 源码地址 https://github.com/lemonbar ...
- table表格边框样式
; border-left:1px solid #aaa; border-top:1px solid #aaa; } td{border-right:1px solid #aaa; border-bo ...
- Maven .m2 setting.xml配置
settings.xml <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="h ...
- BuguMongo是一个MongoDB Java开发框架,集成了DAO、Query、Lucene、GridFS等功能
http://code.google.com/p/bugumongo/ 简介 BuguMongo是一个MongoDB Java开发框架,它的主要功能包括: 基于注解的对象-文档映射(Object-Do ...
- [置顶] VB6基本数据库应用(三):连接数据库与SQL语句的Select语句初步
同系列的第三篇,上一篇在:http://blog.csdn.net/jiluoxingren/article/details/9455721 连接数据库与SQL语句的Select语句初步 ”前文再续, ...
- C#控制台吹泡泡算法
代码如下: static void Main(string[] args) { Bubbling(100, 100, "O", 1000); Console.ReadLine(); ...
- vsim生成VCD波形文件(verilog)
Vsim(ModelSim)生成VCD波形文件(verilog) 两种方法 方法一: 调用ModelSim自己的命令生成,仿真脚本中加入如下一句即可 vcd file mytb.vcd 方法二: 调用 ...
- .NET 4.0 兼容 .NET 2.0 的方法
使用.net开发桌面应用,广大亲门最头疼的莫过于客户端部署的问题.基于.net 2.0 的winfrom程序因为 Framework 的分发包大小为20M左右还好解决,不幸的是如果项目中使用了Wcf, ...