Description
Issue 最近迷上了一款字符串游戏。游戏要求玩家维护一个由小写字母组成的字符串,并回答一些询问。
具体的,初始时玩家会获得一个长度为 (n(nle 10^5)) 的字符串,接下来游戏进行 (m(mle 10^5)) 轮,每轮可能是
如下两种情况:
- 求出子串 ([l, r]) 的字典序最大的子序列,并输出该子序列的第 (k) 个字符。若该子序列长度不足 (k) ,则输出“-”(不含引号)
- 修改字符串的第 (i) 位为字符 (c)
由于游戏的轮数太多了,Issue 有点忙不过来了,快来帮帮她!
Solution
线段树。每个点维护此区间的最大字母、出现次数、最靠右出现位置。
每次就把区间内最大的字母串在一起,然后迭代到接下来的区间。详见代码。
复杂度 (O(26mlog_2n))
#include<bits/stdc++.h>
using namespace std;
template <class T> inline void read(T &x) {
x = 0; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0';
}
#define N 100001
#define rep(i, a, b) for (int i = a; i <= b; i++)
char s[N];
int n, Max[N << 2], cnt[N << 2], rig[N << 2];
#define ls rt << 1
#define rs ls | 1
#define mid (l + r >> 1)
inline void pushUp(int rt) {
Max[rt] = cnt[rt] = rig[rt] = 0;
Max[rt] = max(Max[ls], Max[rs]);
if (Max[rt] == Max[ls]) cnt[rt] += cnt[ls], rig[rt] = rig[ls];
if (Max[rt] == Max[rs]) cnt[rt] += cnt[rs], rig[rt] = rig[rs];
}
void build(int rt, int l, int r) {
if (l == r) { Max[rt] = s[l] - 'a', cnt[rt] = 1, rig[rt] = l; return; }
build(ls, l, mid), build(rs, mid + 1, r);
pushUp(rt);
}
void update(int rt, int l, int r, int p, int v) {
if (l == r) { Max[rt] = v; return; }
if (p <= mid) update(ls, l, mid, p, v);
else update(rs, mid + 1, r, p, v);
pushUp(rt);
}
#define pii pair<int, int>
#define fr first
#define sc second
pii query(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) { return pii(cnt[rt], rig[rt]); }
if (R <= mid) return query(ls, l, mid, L, R);
if (L > mid) return query(rs, mid + 1, r, L, R);
pii ansl = query(ls, l, mid, L, R), ansr = query(rs, mid + 1, r, L, R);
if (s[ansl.sc] == s[ansr.sc]) return pii(ansl.fr + ansr.fr, ansr.sc);
else return s[ansl.sc] > s[ansr.sc] ? ansl : ansr;
}
int main() {
char ch = getchar();
for (; ch >= 'a' && ch <= 'z'; ch = getchar()) s[++n] = ch;
build(1, 1, n);
int Q; read(Q);
while (Q--) {
int op; read(op);
if (op == 1) {
int l, r, k, len = 0; read(l), read(r), read(k);
pii t;
for (; l <= r; l = t.sc + 1) {
t = query(1, 1, n, l, r);
len += t.fr; if (len >= k) break;
}
if (l > r) puts("-");
else putchar(s[t.sc]), puts("");
}
else {
int p; read(p);
char c = getchar();
for (; c > 'z' || c < 'a'; c = getchar());
// printf("%d gay %c
",p, c);
s[p] = c, update(1, 1, n, p, c - 'a');
}
}
return 0;
}