3 ABC411 C~E 题解

ABC411 C~E 题解

又是赤石的一天

C

有个长度为 \(N\) 的序列,初始序列中每个数为0

每次操作给定 \(pos\) ,将 pos^1 ,然后输出序列中有多少段不连续的 1

用小样例模拟一下可得,设当前颜色为 \(b\) ,左边颜色为 \(a\) ,右边颜色为 \(c\) ,序列中不连续 1 的段数为 \(cnt\)

  • \(a\ne b\ 且\ b \ne c\ \to\ cnt \verb|-=|1\)
  • \(a = b\ 且\ b = c\ \to\ cnt \verb|+=|1\)

D

有一台服务器和 \(N\) 台 PC 。服务器和每台 PC 各持有一个字符串,最初所有字符串都是空的。PC 从 \(1 \sim N\) 编号

给出了 \(Q\) 个操作。每个操作都是以下格式之一:

  • 1 p:用 服务器 的字符串替换 \(p\) 的字符串。
  • 2 p s:在 \(p\) 字符串的末尾添加字符串 \(s\)
  • 3 p:用 \(p\) 的字符串替换 服务器 的字符串。

按照给定的顺序处理所有查询后,找出 服务器 的最终字符串。

一开始我想用 string 水过,但 T 飞了,因为 string 赋值操作的时间复杂度是 O(len) 的,后来查了查,发现 string 的很多操作都是 O(len) 的,以后要慎用

下面是正解

用链表来记录下每个 PC 的尾部字符串的编号,以及每个字符串的父串 (注意不能记录每个节点的子节点,这样在修改尾部时会丢失信息)

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 2e5 + 10;

int n, m;
int f[N], p[N];
string s[N];

int main () {

	scanf ("%d%d", &n, &m);
	memset (p, -1, sizeof p);

	int rt = 0, cnt = 0;
	for (int i = 1; i <= m; i++) {
		int op, x;
		cin >> op >> x;
		if (op == 1) {
			p[x] = p[rt];
		} else if (op == 2) {
			cin >> s[++cnt];
			if (p[x] == -1) {
				p[x] = cnt;
				f[cnt] = -1;
			} else {
				f[cnt] = p[x];
				p[x] = cnt;
			}
		} else {
			p[rt] = p[x];
		}
	}

	vector <string> ans;
	for (int i = p[rt]; i != -1; i = f[i]) {
		ans.push_back (s[i]);
	}
	for (int i = (int)ans.size() - 1; i >= 0; i--) {
		cout << ans[i];
	}
	cout << endl;
	
	return 0;
}
posted @ 2025-10-10 21:12  michaele  阅读(8)  评论(0)    收藏  举报