题解:Luogu_P1383_高级打字机
题解:Luogu_P1383_高级打字机
Luogu_P1383_高级打字机
可持久化线段树
Solution
首先看到有撤销操作,想到用可持久化线段树维护,建树时直接用 \(1\sim m\) 区间建,每个节点存一个字符和 \(siz\),用于找下标。
- 新增节点:在对应位置新增,记录 \(siz\),记得 \(pushup\),如果左子树 \(siz\) 等于 \(mid-l+1\),那么说明左子树满了,递归右子树
- 撤销操作:直接新建一个当前版本的根指向撤销操作的根
- 查询操作:按照 \(siz\),慢慢找
Code
记得把数组开大一点!!!
//P1383 (AC)
#include <iostream>
using namespace std;
const int N = 1e6 + 5;
int n, m, rnt, root[N];
struct node
{
int ls, rs, siz;
char val;
node(int _ls = 0, int _rs = 0, int _siz = 0, char _val = ' ')
{
ls = _ls, rs = _rs, siz = _siz, val = _val;
}
} t[N << 2];
int update(int rt, int l, int r, char val)
{
int p = ++ n;
t[p] = t[rt];
if (l == r)
{
t[p].val = val;
t[p].siz = 1;
return p;
}
int mid = l + r >> 1;
if (t[t[p].ls].siz >= mid - l + 1)
t[p].rs = update(t[rt].rs, mid + 1, r, val);
else
t[p].ls = update(t[rt].ls, l, mid, val);
t[p].siz = t[t[p].ls].siz + t[t[p].rs].siz;
return p;
}
char query(int p, int l, int r, int pos)
{
if (l >= r)
return t[p].val;
int mid = l + r >> 1;
if (pos <= t[t[p].ls].siz)
return query(t[p].ls, l, mid, pos);
else
return query(t[p].rs, mid + 1, r, pos - t[t[p].ls].siz);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> m;
char opt, ch;
for (int val, i = 1; i <= m; i ++)
{
cin >> opt;
if (opt == 'T')
{
cin >> ch;
rnt ++;
root[rnt] = update(root[rnt - 1], 1, m, ch);
continue;
}
if (opt == 'U')
{
cin >> val;
rnt ++;
root[rnt] = root[rnt - val - 1];
continue;
}
if (opt == 'Q')
{
cin >> val;
cout << query(root[rnt], 1, m, val) << endl;
}
}
return 0;
}

浙公网安备 33010602011771号