URAL 1989. Subpalindromes
- 题意:对一个字符串有两个操作:(1)查询区间[l, r]子串是不是回文串. (2)修改某个位置上的字符
- 思路:这个有点显然是线段树,但问题就是我们应该用线段树维护什么?
- 我们用线段树维护的当然是两个值:Lval(正串的哈希值),Rval(反串的哈希值)。那么问题又来了,是整个串的哈希值还是区间子串的哈希值呢?
- 这里我用的是整个串的哈希值,区间外的“数位”上权值为0.
举个栗子【做题的时候打的草稿,不要嫌弃┭┮﹏┭┮】
但是不知道大家有没有意识到一个问题:
注意
- 如果查询区间长度是奇数,那么要去掉中间的那个字符。【这就要求我们长度为1时要特判为Yes】
- 建树时,字符串是[0, n - 1],但是线段树是[1, n],不要写飘了【其实是我自己写飘了www】
- 还有就是结构体'+'重载,返回类型是node. qwq
- END
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define MID (r + l) >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid + 1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 7;
const ull base = 233;
ull p[maxN];
char ans[2][10], s[maxN];
int n, m;
void init()
{
strcpy(ans[0], "No");
strcpy(ans[1], "Yes");
p[0] = 1;
for(int i = 1; i <= n; i ++ )
p[i] = p[i - 1] * base;
}
struct node{
ull Lval, Rval;
node() {}
node(ull a, ull b) : Lval(a), Rval(b) {}
friend node operator + (node n1, node n2) { return node(n1.Lval + n2.Lval, n1.Rval + n2.Rval); }
}tree[maxN << 2];
void pushup(int rt) { tree[rt] = tree[lsn] + tree[rsn]; }
void build_tree(int rt, int l, int r)
{
if(l == r)
{
tree[rt] = node((s[l - 1] - 'a' + 1) * p[l - 1], (s[r - 1] - 'a' + 1) * p[n - r]);
return ;
}
int mid = MID;
build_tree(Lson);
build_tree(Rson);
pushup(rt);
}
void update_pos(int rt, int l, int r, int pos, ull val)
{
if(l == r)
{
tree[rt] = node(val * p[l - 1], val * p[n - r]);
return ;
}
int mid = MID;
if(pos <= mid) update_pos(Lson, pos, val);
else update_pos(Rson, pos, val);
pushup(rt);
}
node query(int rt, int l, int r, int ql, int qr)
{
if(ql <= l && qr >= r)
return tree[rt];
int mid = MID;
if(qr <= mid) return query(QL);
else if(ql > mid) return query(QR);
else return query(QL) + query(QR);
}
int main()
{
scanf("%s", s);
n = strlen(s);
init();
build_tree(1, 1, n);
scanf("%d", &m); getchar();
char q[20];
while(m -- )
{
scanf("%s", q);
if(q[0] == 'p')
{
int ql, qr; scanf("%d%d", &ql, &qr);
if(qr - ql + 1 == 1)
{
printf("Yes\n");
continue;
}
int md = (ql + qr) >> 1;
node ans1, ans2;
if((qr - ql + 1) & 1)
{
ans1 = query(1, 1, n, ql, md - 1);
ans2 = query(1, 1, n, md + 1, qr);
}
else
{
ans1 = query(1, 1, n, ql, md);
ans2 = query(1, 1, n, md + 1, qr);
}
if(ql - 1 <= n - qr)
ans1.Lval *= p[(n - qr) - (ql - 1)];
else
ans2.Rval *= p[(ql - 1) - (n - qr)];
printf("%s\n", ans[ans1.Lval == ans2.Rval]);
}
else
{
int pos; char tar[2];
scanf("%d %s", &pos, tar);
update_pos(1, 1, n, pos, (ull)(tar[0] - 'a' + 1));
}
}
return 0;
}
/*
aaaaaabbbb
3
c 6 c
c 8 c
p 6 8
*/