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;
}

浙公网安备 33010602011771号