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;
}