版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/82429301
【题目链接】
【思路要点】
- 利用 对新产生的后缀动态标号,维护一棵后缀平衡树,再用线段树支持修改即可。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5e5 + 5;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
struct Treap {
struct Node {
ull val, var;
unsigned weight;
int child[2], father;
} a[MAXN];
int root, n;
unsigned seed;
char s[MAXN];
bool labeled[MAXN];
unsigned Rand() {
seed = seed * seed + rand();
return seed;
}
bool cmp(int x, int y) {
if (x == y) return false;
if (x == 0) return true;
if (y == 0) return false;
if (labeled[x] && labeled[y]) return a[x].val + a[x].var < a[y].val + a[y].var;
else {
if (s[x] == s[y]) return cmp(x - 1, y - 1);
else return s[x] < s[y];
}
}
bool get(int pos) {
return pos == a[a[pos].father].child[1];
}
void rotate(int x) {
int f = a[x].father, g = a[f].father;
bool tmp = get(x);
a[x].father = g;
if (g) a[g].child[get(f)] = x;
a[f].child[tmp] = a[x].child[tmp ^ 1];
a[a[x].child[tmp ^ 1]].father = f;
a[f].father = x;
a[x].child[tmp ^ 1] = f;
if (g == 0) root = x;
}
void label(int &root, int pos, int f) {
if (root == 0) {
root = pos;
a[pos].father = f;
return;
}
if (cmp(pos, root)) {
label(a[root].child[0], pos, root);
if (a[a[root].child[0]].weight < a[root].weight) rotate(a[root].child[0]);
} else {
label(a[root].child[1], pos, root);
if (a[a[root].child[1]].weight < a[root].weight) rotate(a[root].child[1]);
}
}
void dfs(int pos) {
ull mid = (a[pos].val + a[pos].var) / 2;
if (a[pos].child[0]) {
a[a[pos].child[0]].val = a[pos].val;
a[a[pos].child[0]].var = mid - 1;
dfs(a[pos].child[0]);
}
if (a[pos].child[1]) {
a[a[pos].child[1]].val = mid + 1;
a[a[pos].child[1]].var = a[pos].var;
dfs(a[pos].child[1]);
}
}
void label(int pos) {
a[pos].weight = Rand();
label(root, pos, 0);
labeled[pos] = true;
if (pos == root) a[root].val = 0, a[root].var = 1ull << 63;
else {
int f = a[pos].father;
ull tmp = (a[f].val + a[f].var) / 2;
if (get(pos)) a[pos].var = a[f].var, a[pos].val = tmp + 1;
else a[pos].val = a[f].val, a[pos].var = tmp - 1;
}
dfs(pos);
}
void insert(char c) {
s[++n] = c;
label(n);
}
void init(int len) {
root = 1, seed = 1, n = len;
labeled[root] = true;
a[root].weight = Rand();
a[root].val = 0, a[root].var = 1ull << 63;
scanf("\n%s", s + 1);
reverse(s + 1, s + len + 1);
for (int i = 2; i <= n; i++)
label(i);
}
} Treap;
char s[MAXN];
int n, m, len, type, p[MAXN];
struct SegmentTree {
struct Node {
int lc, rc;
int home;
} a[MAXN * 2];
int n, root, size;
void update(int root) {
if (Treap.cmp(p[a[a[root].rc].home], p[a[a[root].lc].home])) a[root].home = a[a[root].rc].home;
else a[root].home = a[a[root].lc].home;
}
void build(int &root, int l, int r) {
root = ++size;
if (l == r) {
a[root].home = l;
return;
}
int mid = (l + r) / 2;
build(a[root].lc, l, mid);
build(a[root].rc, mid + 1, r);
update(root);
}
void init(int x) {
n = x;
root = size = 0;
build(root, 1, n);
}
void modify(int root, int l, int r, int pos) {
if (l == r) return;
int mid = (l + r) / 2;
if (mid >= pos) modify(a[root].lc, l, mid, pos);
else modify(a[root].rc, mid + 1, r, pos);
update(root);
}
void modify(int pos) {
modify(root, 1, n, pos);
}
int query(int root, int l, int r, int ql, int qr) {
if (l == ql && r == qr) return a[root].home;
int mid = (l + r) / 2;
if (mid >= qr) return query(a[root].lc, l, mid, ql, qr);
else if (mid + 1 <= ql) return query(a[root].rc, mid + 1, r, ql, qr);
else {
int tmp = query(a[root].lc, l, mid, ql, mid);
int tnp = query(a[root].rc, mid + 1, r, mid + 1, qr);
if (Treap.cmp(p[tnp], p[tmp])) return tnp;
else return tmp;
}
}
int query(int l, int r) {
return query(root, 1, n, l, r);
}
} ST;
char getopt() {
char ch = getchar();
while (ch != 'C' && ch != 'Q' && ch != 'I') ch = getchar();
return ch;
}
int main() {
read(n), read(m), read(len), read(type);
Treap.init(len);
int lastans = 0;
for (int i = 1; i <= n; i++)
read(p[i]);
ST.init(n);
for (int i = 1; i <= m; i++) {
char opt = getopt();
if (opt == 'I') {
int tmp; read(tmp);
tmp ^= lastans * type;
Treap.insert(tmp + 'a');
}
if (opt == 'C') {
int pos; read(pos);
read(p[pos]);
ST.modify(pos);
}
if (opt == 'Q') {
int l, r; read(l), read(r);
printf("%d\n", lastans = ST.query(l, r));
}
}
return 0;
}