思路:考虑
d
p
i
j
dp_{ij}
dpij表示在一个
i
f
if
if框内,执行到第
i
i
i次操作时,获得值为
j
j
j的最小花费。初始只有进入该
i
f
if
if时的初值有一个代价,其余都是无穷大。
那么如果时
s
e
t
y
v
set ~~y~~v
set y v的话,任意不等于
y
y
y的值都必须花费
v
v
v的代价来跳过这一次操作从而不成为
y
y
y,而
y
y
y可以从其他任意值转移过来(注意不能等于
x
x
x)。那么这样就可以用一个线段树来维护一下全局最小值,另外需要支持单点查询。维护完所有的操作后,就能知道每个值的最小代价了。
这是一个
i
f
if
if框的情况,对于多个
i
f
if
if,显然不能每个都开一个线段树,但是我们注意到,每个
i
f
if
if框内有效的数的总和是
N
N
N级别的。那么就可以对每个
i
f
if
if框动态建一个线段树来维护最小值。然后嵌套的框就合并起来。
合并的时候注意如果有一个为
n
u
l
l
null
null就直接返回另一个不然复杂度就不对了。
细节见代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mid (l+r>>1)
#define wzh(x) cerr<<#x<<'='<<x<<endl;
int n,s;
const LL MX=1e18;
struct uzi{
LL mn,tag;
uzi *ls,*rs;
};
uzi * new_node(){
auto tmp=new uzi;
tmp->mn=MX;
tmp->tag=0;
tmp->ls=tmp->rs=NULL;
return tmp;
}
void push_up(uzi * o){
LL res=MX;
if(o->ls!=NULL)res=min(res,o->ls->mn);
if(o->rs!=NULL)res=min(res,o->rs->mn);
o->mn=res;
}
void add(uzi *o,LL val){
o->tag+=val;
o->mn+=val;
}
void push_down(uzi *o){
if(o->tag){
if(o->ls!=NULL)add(o->ls,o->tag);
if(o->rs!=NULL)add(o->rs,o->tag);
o->tag=0;
}
}
void up(uzi * &o,int l,int r,int x,LL y){
if(o==NULL)o=new_node();
if(l==r){
o->mn=y;
return;
}
push_down(o);
if(x<=mid)up(o->ls,l,mid,x,y);
else up(o->rs,mid+1,r,x,y);
push_up(o);
}
LL get(uzi *o,int l,int r,int x){
if(o==NULL)return MX;
if(l==r){
return o->mn;
}
push_down(o);
if(x<=mid)return get(o->ls,l,mid,x);
else return get(o->rs,mid+1,r,x);
}
uzi * merge(uzi *x,uzi *y){
if(x==NULL)return y;
if(y==NULL)return x;
x->mn=min(x->mn,y->mn);
push_down(x);
push_down(y);
x->ls=merge(x->ls,y->ls);
x->rs=merge(x->rs,y->rs);
return x;
}
string S;
uzi * solve(int now,LL val){
uzi * tmp=new_node();
up(tmp,0,N,now,val);
int y,v;
while(cin>>S){
if(S[0]=='s'){
cin>>y>>v;
LL now_min=tmp->mn;
tmp->tag+=v;
tmp->mn+=v;
if(y!=s)up(tmp,0,N,y,now_min);
}else if(S[0]=='i'){
cin>>y;
auto res=solve(y,get(tmp,0,N,y));
up(tmp,0,N,y,MX);//把y的值给清掉,因为内层if已经更新了y的值。
tmp=merge(tmp,res);
}else{
return tmp;
}
}
return tmp;
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>s;
cout<<solve(0,0)->mn<<'\n';
return 0;
}