window.cnblogsConfig = {//可以放多张照片,应该是在每一个博文上面的图片,如果是多张的话,那么就随机换的。 homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png", "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png" ], }

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;
}
posted @ 2024-01-18 07:45  CCF_IOI  阅读(21)  评论(0)    收藏  举报