可持久化数据结构维护可持久化数组

可持久化数据结构维护可持久化数组

首先我们要知道,"UNDO"操作,也就是直接跳回前面的操作(历史操作),然后跳回的地方到现在的地方这一个区间的操作都不用管。(这就是高级挑战的思路)

(可持久化是指一种可以访问历史版本的数据结构)然后我们就可以知道,询问历史,又是数组,也就是可持久化数组。可持久化数组的维护很简单,我们可以开一个\(O(N^2)\)的矩阵,然后进行操作。但是这样子空间会爆炸,怎么办?所以可持久化数组又可以用可持久化线段树来维护,虽然有很多空间浪费了,不过空间也还是\(O(N\ log\ N)\)(因为每一个数带来的空间是\(log\ n\)的)。

所以就这样子咯,如果还不会可持久化线段树(主席树)的可以去做洛谷的模板。

// luogu-judger-enable-o2
var
        n,cnt,hao,tot:longint;
        len,lson,rson,root:array[0..2000035] of longint;
        value:array[0..2000035] of char;
        s:string;
        HuHa:char;

procedure build(var rt:longint; fa,l,r,po:longint); //插入一个数
var
        mid:longint;
begin
        if (rt=0) then
        begin
                inc(tot);
                rt:=tot; //动态开点
        end;
        if l=r then //到了叶子节点
        begin
                value[rt]:=HuHa; //赋值
                exit; //退出
        end;

        mid:=(l+r) div 2;
        if (po<=mid) then //po就是key位置,我现在在最后(一个栈)插入一个数,po就是最后的位置
        begin
                rson[rt]:=rson[fa]; //垃圾回收
                build(lson[rt],lson[fa],l,mid,po); //左走
        end;
        if (po>=mid+1) then //同上
        begin
                lson[rt]:=lson[fa];
                build(rson[rt],rson[fa],mid+1,r,po);
        end;
end;

function Query(rt,l,r,po:longint):char; //查询
var
        mid:longint;
begin
        if l=r then //到了指定位置(不一定是po)
                exit(value[rt]);
        mid:=(l+r) div 2; // 线段树常识
        if (po<=mid) then
                exit(Query(lson[rt],l,mid,po));
        if (po>=mid+1) then
                exit(Query(rson[rt],mid+1,r,po));
end;

begin
        readln(n);
        while n>0 do
        begin
                readln(s);
                if s[1]='T' then
                begin
                        HuHa:=s[3]; //直接截取
                        inc(cnt);
                        len[cnt]:=len[cnt-1]+1; //新的位置 
                        Build(root[cnt],root[cnt-1],1,100007,len[cnt]); //插入
                end;

                if s[1]='U' then
                begin
                        delete(s,1,2);
                        val(s,hao);
                        inc(cnt);
                        len[cnt]:=len[cnt-hao-1]; //位置往前推
                        root[cnt]:=root[cnt-hao-1]; //Root往前推(没一个数都有一个log链,当然有一个根)
                end;

                if s[1]='Q' then
                begin
                        delete(s,1,2);
                        val(s,hao);
                        writeln(Query(root[cnt],1,100007,hao)); // 查询,我们不知道最长的长度是多少,所以就100007就可以了,log不会超过20
                end;
                dec(n);
        end;
end.
posted @ 2018-09-23 15:14  _ARFA  阅读(205)  评论(0编辑  收藏  举报