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 ...
随机推荐
- libeXosip2(2-2) -- eXosip2 network API
eXosip2 network API General purpose API. Functions int eXosip_transport_set (osip_message_t *msg, c ...
- phpcms:五、网站首页(index.html)
1.经典案例:图文列表:{pc:content action="position" posid="2" order="listorder DESC& ...
- Activity小结
Log日志类的五种级别 1.由高到低分别是:v.i.d.w.e 2.生命周期有七种状态: onCreate:创建 onStart:启动 onResume:显示(可以与用户交互) onPause:暂停 ...
- CentOS7 定时检测进程占用内存大小,执行重启进程操作(xjl456852原创)
在使用CentOS时,个别程序的进程会一直增大,直到宕机.但是这种程序本身有没有更好的版本使用(比如ngrok免费就这样,付费的就没这个问题),所以想写一个脚本定时检测一下这个程序的情况,决定是否需要 ...
- 在ubuntu14.04上部署hadoop2.6.3
一.在Ubuntu下创建hadoop组和hadoop用户 增加hadoop用户组,同时在该组里增加hadoop用户,后续在涉及到hadoop操作时,我们使用该用户. 1.创建hadoop用户组 2.创 ...
- wpf新增记录时用多线程的问题
多线程虽然可以增加用户操作体验,但是有时候会出现意想不到的错误. 如果采用分布式,数据库在另外服务器上,当网络出现问题,或者数据库繁忙,那么新增数据就会等待,这时候用户如果以为没有操作,而多次点击新增 ...
- [RxJS] Creating Observable From Scratch
Get a better understanding of the RxJS Observable by implementing one that's similar from the ground ...
- android 中文件加密 解密 算法实战
现在项目里面有一个需求,本项目里面下载的视频和文档都不允许通过其他的播放器播放,在培训机构里面这样的需求很多.防止有人交一份钱,把所有的课件就拷给了别人.这样的事情培训机构肯定是不愿意的.现在我项目里 ...
- js Date扩展Format()函数
Date.prototype.Format = function (formatStr) { var str = formatStr; var Week = ['日', '一', '二', '三', ...
- Java中构造方法的执行顺序
一.先执行内部静态对象的构造方法,如果有多个按定义的先后顺序执行:静态对象在构造的时候也是也先执行其内部的静态对象. 二.再调用父类的构造方法(父类还有父类的话,从最开始的基类开始调用),如果没有明显 ...