传送门
考虑设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示读完第
i
i
i行语句后,若
x
x
x值为
j
j
j所需要花费的最小代价。
假设本题只有
s
e
t
set
set语句,那么我们不难发现,每当遇到语句
s
e
t
y
v
set\;y\;v
setyv时我们只需要更新
∀
j
≠
y
,
d
p
[
i
]
[
j
]
+
=
v
\forall j\ne y,dp[i][j]+=v
∀j=y,dp[i][j]+=v以及
d
p
[
i
]
[
y
]
=
m
i
n
k
{
d
p
[
i
−
1
]
[
k
]
}
dp[i][y]=min_{k}\{dp[i-1][k]\}
dp[i][y]=mink{dp[i−1][k]},也就是实现一个全局加和单点修改的功能即可,至于求最小值我们考虑用
m
u
l
t
i
s
e
t
multiset
multiset来维护。
具体来说,我们用懒标记
a
d
ad
ad表征全局的增益,一个
m
a
p
map
map数组
d
p
[
j
]
dp[j]
dp[j]来记录第
i
i
i条语句对应的
d
p
dp
dp值,将这些值放入
m
u
l
t
i
s
e
t
multiset
multiset中,更新的时候取
m
u
l
t
i
s
e
t
multiset
multiset中的最小值更新
d
p
[
y
]
dp[y]
dp[y]即可。
本题稍微复杂的就是加入了 i f if if语句,进入 i f y if\;y ify语句显然只能从 d p [ y ] dp[y] dp[y]的这个状态转移过去,也就是说一旦进入 i f if if语句,那么最基础的成本就是 d p [ y ] dp[y] dp[y]了,并且起始数字一定是 x = y x=y x=y,注意到整个游戏开始的时候,我们的 x = 0 x=0 x=0,对应的基础成本是 0 0 0,起始本质上 i f if if语句内的情况是一样的,只是初始条件不同,因此我们一旦进入 i f if if中(如果可以进入)就新开一个 d p dp dp数组,单独更新,对应的初始条件是 d p [ y ] dp[y] dp[y],更新完毕后,若退出了 i f if if块,那么我们就这个新的 d p dp dp数组与外面的 d p dp dp数组合并,也就是说对所有的 d p [ j ] dp[j] dp[j]可能存在两个值,那么取最小的那个即可。如果还有 i f if if的嵌套的话,我们继续开新的 d p dp dp数组,具体来说,这么多的 d p dp dp数组存在父子关系,我们用栈维护即可,退出 i f if if块的时候弹栈并将两个 d p dp dp数组合并,进入 i f if if块的时候 p u s h push push新的 d p dp dp数组。
struct Node{
multiset<ll>s;
unordered_map<int,ll>dp;
ll ad=0;
};
vector<Node>g;
void upd(Node &a,int x,ll v){
if(a.dp.count(x)){
a.s.erase(a.s.find(a.dp[x]));
}
a.dp[x]=v;
a.s.insert(v);
}
int gnew(int x,ll v){
g.push_back({});
g.back().dp[x]=v;
g.back().s.insert(v);
g.back().ad=0;
return (int)g.size()-1;
}
char ch[10];
int main(){
int t=rd(),s=rd();
int u=gnew(0,0),skip=0;
while(t--){
int y,v;
rds(ch);
if(ch[0]=='s'){
y=rd(),v=rd();
if(skip)continue;
ll mi=*g[u].s.begin()-v;
g[u].ad+=v;
if(y!=s)upd(g[u],y,mi);
}else if(ch[0]=='i'){
y=rd();
if(skip || !g[u].dp.count(y)){
skip++;
continue;
}
int vv=gnew(y,g[u].dp[y]+g[u].ad);
g[u].s.erase(g[u].s.find(g[u].dp[y]));
g[u].dp.erase(y);
u=vv;
}else{
if(skip)skip--;
else {
unordered_map<int,ll>::iterator it1,it2;
if(g[u].dp.size()>g[u-1].dp.size())swap(g[u],g[u-1]);
for(it1=g[u].dp.begin(),it2=g[u].dp.end();it1!=it2;it1++){
if(!g[u-1].dp.count(it1->first) || g[u-1].dp[it1->first]+g[u-1].ad>it1->second+g[u].ad){
upd(g[u-1],it1->first,it1->second+g[u].ad-g[u-1].ad);
}
}
g.pop_back();
u--;
}
}
}
wrn(*g[u].s.begin()+g[u].ad);
}