ABC273E解题报告
题意
有一个初始为空的当前列表,和一个版本保存系统,共 \(10^9\) 个版本
进行 \(q\) 次操作,有四种类型的操作:
ADD x
:在当前列表的末尾添加 \(x\)DELETE
:如果当前列表非空,把当前列表的末尾最后一个数删除。否则,什么也不做。SAVE x
:把当前列表保存至第 \(x\) 版本(保存后当前列表不清空)LOAD x
:把当前列表变成第 \(x\) 版本(直接赋值,保存后第 \(x\) 版本不清空)。
求每次操作后当前列表的末尾最后一个数(若当前列表为空输出 \(-1\))。
分析
考虑暴力,把每一个版本都存一次,肯定炸。肯定是用一个数组去维护当前版本,很多个数组去维护这些保存的版本。
很明显当前版本是一个链表,用数组模拟链表,一个 \(val\) 数组表示这个元素的值,\(fa\) 数组表示这个链表上一个元素的位置,当前列表最后一个数位置为 \(now\)。
添加和删除操作都是在尾部进行的不会影响到前面的值,那么我们的存档操作可以直接记录 \(now\),然后读档时直接更新 \(now\) 到保存的位置上。
这又引出一个问题,如何处理删除操作又不影响当前列表?不难想到直接更改 \(now\) 就好了,因为在添加的时候是将新来的数挂在 \(now\) 后面的,直接把前面删去的数覆盖了(虽然此时可能又多个数的 \(fa\) 是 \(now\),但是在添加操作的时候只会把 \(now\) 更新到最新的数上,保存也只会保存到 \(now\),和那些 \(fa\) 相同的无关)。
最后输出部分,我们的下标都是从 \(1\) 开始的,而且所有输入的值都是大于 \(1\) 的,只要判断 \(val_{now}\) 是否大于 \(0\)。
注意,存档时的 \(x\) 高达 \(1 \times 10^9\),需要使用 map 去存是哪一个存档对应的位置。
代码
#include <bits/stdc++.h>
using namespace std;
int n, x, pos, now;
int val[500005], fa[500005];
string opt;
map<int, int> save;
int main(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> opt;
if (opt == "ADD"){
cin >> x;
fa[++pos] = now;//类似链表的加入
val[pos] = x;
now = pos;//跳到最新的上面
}
if (opt == "DELETE") now = fa[now];//只需要挪动now就行
if (opt == "SAVE"){
cin >> x;
save[x] = now;//存档时只需要存位置
}
if (opt == "LOAD"){
cin >> x;
now = save[x];
}
cout << ((val[now] == 0) ? -1 : val[now]) << endl;//判断是否为空
}
return 0;
}