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 ...
随机推荐
- BHO多线程中实现右键菜单
在BHO中实现右键菜单网上相关文章很多,可以通过实现IDocHostUIHandler接口的ShowContextMenu.截获HTMLDocumentEvents2的OnContextMenu消息等 ...
- POJ2367 Genealogical tree (拓扑排序)
裸拓扑排序. 拓扑排序 用一个队列实现,先把入度为0的点放入队列.然后考虑不断在图中删除队列中的点,每次删除一个点会产生一些新的入度为0的点.把这些点插入队列. 注意:有向无环图 g[] : g[i] ...
- c语言中break continue goto return和exit的区别 联系(筛选奇数和goto求和)
break 一般你是用于循环和switch语句中,执行break,退出循环,如果是多层循环,那么退出的当前的循环. 如果循环结构中有switch语句,而switch语句中有break 那么不会直接退出 ...
- c语言结构体5之匿名结构体
注意: 1匿名结构体不会出现重合 重命名的情况 2有名结构体 名称不能相同 也就是不能重名 //匿名结构体不会出现重名的情况 struct //无名结构体 { ]; ]; int num; };//不 ...
- MyBatis魔法堂:Insert操作详解
一.前言 数据库操作怎能少了INSERT操作呢?下面记录MyBatis关于INSERT操作的笔记,以便日后查阅. 二. insert元素 属性详解 其属性如下: parameterType:入参的全限 ...
- MapReduce新版客户端API源码分析
使用MapReduce新版客户端API提交MapReduce Job需要使用 org.apache.hadoop.mapreduce.Job 类.JavaDoc给出以下使用范例. // Create ...
- Servlet实现文件的下载
(1)项目的主文件夹例如以下:(演示出image和servlet的位置所在) watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGxnZW4xNTczODc= ...
- CSS基础知识之float
前段时间写过一篇CSS基础知识之position,当时对float的理解不太准确,被慕课网多名读者指出(原文已修正,如有误导实在抱歉).现对float进行更深入的学习,在此把学习心得分享给大家. 浮动 ...
- DataTable复制自身行
在我们工作的过程中有可能要使用DataTable产生一些重复数据(在不重复读取数据库的情况下) 无废话,直接上代码 DataTable复制自身一行(目的产生重复数据),已测试通过可直接复制 /// & ...
- Hadoop高可用平台搭建
文章概览: 1.机器规划和预配置 2.软件安装 3.集群文件配置 4.启动集群 5.HA验证 6.注意事项 7.小结 机器规划和预配置 主机/进程 NN DN RM NM ZK(QP) ZKFC ...