开二十六颗线段树,替换就把第x棵线段树的[l,r]分裂出来合并到第y棵线段树上
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int n, m;
struct Node
{
int l, r;
int v;
}tr[N * 50];
int root[30], idx;
char str[N];
void modify(int l, int r, int &u, int x, int k)
{
if (!u) u = ++ idx; // 动态开点
if (l == r)
{
tr[u].v = k;
return ;
}
int mid = l + r >> 1;
if (x <= mid) modify(l, mid, tr[u].l, x, k);
else modify(mid + 1, r, tr[u].r, x, k);
}
// 分裂
int split(int l, int r, int &u, int x, int y)
{
int p = ++ idx;
if (l >= x && r <= y)
{
tr[p] = tr[u];
u = 0;
}
else
{
int mid = l + r >> 1;
if (x <= mid) tr[p].l = split(l, mid, tr[u].l, x, y);
if (y > mid) tr[p].r = split(mid + 1, r, tr[u].r, x, y);
}
return p;
}
// 合并
void merge(int &x, int y)
{
if (!x || !y){
x |= y;
return ;
}
tr[x].v += tr[y].v;
merge(tr[x].l, tr[y].l);
merge(tr[x].r, tr[y].r);
}
int query(int l, int r, int u, int k)
{
if (l == r) return tr[u].v;
int mid = l + r >> 1;
if (k <= mid) return query(l, mid, tr[u].l, k);
else return query(mid + 1, r, tr[u].r, k);
}
int main()
{
cin >> str + 1 >> m;
n = strlen(str + 1);
for (int i = 1; i <= n; i ++ ) modify(1, n, root[str[i] - 'a'], i, 1); // 动态开点
while (m -- )
{
int l, r; char x, y;
cin >> l >> r >> x >> y;
int p = split(1, n, root[x - 'a'], l, r); // 从 x 树中分裂出来 [l, r]
merge(root[y - 'a'], p); // 合并到 y 树中
}
// 暴力查叶节点 i 在哪棵线段树中
for (int i = 1; i <= n; i ++ )
for (int j = 0; j < 26; j ++ )
if (query(1, n, root[j], i))
{
cout << char (j + 'a');
break;
}
return 0;
}