[不知道哪来的题] string

Description

Issue 最近迷上了一款字符串游戏。游戏要求玩家维护一个由小写字母组成的字符串,并回答一些询问。

具体的,初始时玩家会获得一个长度为 \(n(n\le 10^5)\) 的字符串,接下来游戏进行 \(m(m\le 10^5)\) 轮,每轮可能是
如下两种情况:

  1. 求出子串 \([l, r]\) 的字典序最大的子序列,并输出该子序列的第 \(k\) 个字符。若该子序列长度不足 \(k\) ,则输出“-”(不含引号)
  2. 修改字符串的第 \(i\) 位为字符 \(c\)

由于游戏的轮数太多了,Issue 有点忙不过来了,快来帮帮她!

Solution

线段树。每个点维护此区间的最大字母、出现次数、最靠右出现位置。

每次就把区间内最大的字母串在一起,然后迭代到接下来的区间。详见代码。

复杂度 \(O(26m\log_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\n",p, c);
			s[p] = c, update(1, 1, n, p, c - 'a');
		}
	}
	return 0;
}
posted @ 2018-06-14 14:24  aziint  阅读(147)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.