CF1858E2 Rollbacks (Hard Version) 题解

题目链接

点击打开链接

题目解法

我草,我为什么从来没听过操作树这东西!!!

我理解的操作树是:把加入的点建成一棵树的形式,根到每个点的路径上的点都是某一时刻的状态,操作树可以支持基本所有树上的操作,感觉很强大

回到这道题的 EZ \(version\)
考虑建出操作树,剩下的就很简单
当前序列为根到 \(p\) 的路径,\(+\) 操作想到于给 \(p\) 增加一个儿子,权值为 \(x\)\(-\) 操作想到于 \(p\) 跳到 \(k\) 级祖先,\(!\) 操作可以开个栈记录前面 \(+-\) 操作的最终位置,\(?\) 操作就是查询根到 \(p\) 的路径上的颜色数
离线是可以简单做的,代码就放个链接

在线一个方法是可持久化线段树,但会 MLE
考虑换一种方法
考虑不确切删除数,而是直接覆盖,且打一个 \(tag\),这个可以用栈维护
考虑如何求不同的数的个数,我们只在一个数第一次出现的位置统计,这可以开一个树状数组维护前缀和
具体的不太好说,直接看代码吧

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define pb push_back
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
const int N=1000100;
int n,len,a[N];
stack<pii> stk;
set<int> s[N];
struct BIT{
    int tr[N];
    void add(int x,int v){ for(;x<N;x+=lowbit(x)) tr[x]+=v;}
    int ask(int x){
        int res=0;for(;x;x-=lowbit(x)) res+=tr[x];return res;
    }
}tr;
int main(){
    n=read();ms(a,-1);
    F(i,1,n){
        char op[2];scanf("%s",op);
        if(op[0]=='+'){
            len++;
            if(a[len]!=-1){
                tr.add(*s[a[len]].begin(),-1);
                s[a[len]].erase(len);
                if(!s[a[len]].empty()) tr.add(*s[a[len]].begin(),1);
            }
            stk.push({0,a[len]});
            a[len]=read();
            if(!s[a[len]].empty()) tr.add(*s[a[len]].begin(),-1);
            s[a[len]].insert(len);
            tr.add(*s[a[len]].begin(),1);
        }
        if(op[0]=='-'){
            int k=read();len-=k;
            stk.push({1,k});
        }
        if(op[0]=='?'){ printf("%d\n",tr.ask(len));fflush(stdout);}
        if(op[0]=='!'){
            if(!stk.top().first){
                tr.add(*s[a[len]].begin(),-1);
                s[a[len]].erase(len);
                if(!s[a[len]].empty()) tr.add(*s[a[len]].begin(),1);
                a[len]=stk.top().second;
                if(a[len]!=-1){
                    if(!s[a[len]].empty()) tr.add(*s[a[len]].begin(),-1);
                    s[a[len]].insert(len);
                    tr.add(*s[a[len]].begin(),1);
                }
                len--;
            }
            else len+=stk.top().second;
            stk.pop();
        }
    }
    return 0;
}

posted @ 2023-12-22 23:01  Farmer_D  阅读(8)  评论(0)    收藏  举报