Linux 用户和 OSX 用户一定对软件包管理器不会陌生。
通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。
Debian/Ubuntu 使用的 apt-get,Fedora/CentOS 使用的 yum,以及 OSX 下可用的 homebrew 都是优秀的软件包管理器。
你决定设计你自己的软件包管理器。
不可避免地,你要解决软件包之间的依赖问题。
如果软件包 A 依赖软件包 B,那么安装软件包 A 以前,必须先安装软件包 B。
同时,如果想要卸载软件包 B,则必须卸载软件包 A。
现在你已经获得了所有的软件包之间的依赖关系。
而且,由于你之前的工作,除 0 号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而 0 号软件包不依赖任何一个软件包。
依赖关系不存在环(若有 m(m≥2) 个软件包 A1,A2,A3,…,Am,其中 A1 依赖 A2,A2 依赖 A3A3,A3 依赖 A4,……,Am−1 依赖 Am,而 Am 依赖 A1,则称这 m 个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。
根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。
注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为 0。
输入格式
输入文件的第 1 行包含 1 个正整数 n,表示软件包的总数。软件包从 0 开始编号。
随后一行包含 n−1 个整数,相邻整数之间用单个空格隔开,分别表示 1,2,3,…,n−2,n−1, 号软件包依赖的软件包的编号。
接下来一行包含 1 个正整数 q,表示询问的总数。
之后 q 行,每行 1 个询问。询问分为两种:
install x
:表示安装软件包 xuninstall x
:表示卸载软件包 x
你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。
对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。
输出格式
输出文件包括 q 行。
输出文件的第 i 行输出 1 个整数,为第 i 步操作中改变安装状态的软件包数。
数据范围
输入样例1:
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0
输出样例1:
3
1
3
2
3
输入样例2:
10
0 1 2 1 3 0 0 3 2
10
install 0
install 3
uninstall 2
install 7
install 5
install 9
uninstall 9
install 4
install 1
install 9
输出样例2
1
3
2
1
3
1
1
1
0
1
解析:
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
/*
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
*/
typedef long long LL;
//#define int long long
#define ld long double
//#define INT __int128
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
const ld eps = 1e-12;
const int N = 1e6 + 10, M = N + 10;
int n, m;
int w[N], nw[N];
int h[N], e[M], ne[M], idx;
int id[N], top[N], fa[N], siz[N], dep[N], son[N], tot;
struct TREE {
int l, r;
int fg;
int sum;
}tr[N<<2];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs1(int u, int f, int d) {
//cout << "______________________" << u << endl;
fa[u] = f, dep[u] = d, siz[u] = 1;
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (j == f)continue;
dfs1(j, u, d + 1);
siz[u] += siz[j];
if (siz[son[u]] < siz[j])son[u] = j;
}
}
void dfs2(int u, int t) {
//cout << "______________" << u << endl;
id[u] = ++tot, nw[tot] = w[u], top[u] = t;
if (son[u])dfs2(son[u], t);
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (j == fa[u] || j == son[u])continue;
dfs2(j, j);
}
}
#define ls u<<1
#define rs u<<1|1
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r, tr[u].fg = -1;
if (l == r) {
return;
}
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
}
void up(int u) {
tr[u].sum = tr[ls].sum + tr[rs].sum;
}
void down(int u) {
if (tr[u].fg!=-1) {
tr[ls].fg = tr[u].fg;
tr[ls].sum = tr[u].fg * (tr[ls].r - tr[ls].l + 1);
tr[rs].fg = tr[u].fg;
tr[rs].sum = tr[u].fg * (tr[rs].r - tr[rs].l + 1);
tr[u].fg = -1;
}
}
void modify(int u, int l, int r,int d) {
if (l <= tr[u].l && tr[u].r <= r) {
tr[u].fg = d;
tr[u].sum = d * (tr[u].r - tr[u].l + 1);
return;
}
down(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid)modify(ls, l, r, d);
if (r > mid)modify(rs, l, r, d);
up(u);
}
void updata(int x) {
int rt = 1;
while (top[x] != top[rt]) {
if (dep[top[x]] < dep[top[rt]])swap(x, rt);
modify(1, id[top[x]], id[x], 1);
x = fa[top[x]];
}
if (dep[x] < dep[rt])swap(x, rt);
modify(1, id[rt], id[x], 1);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n;
memset(h, -1, sizeof h);
for (int i = 2; i <= n; i++) {
int a;
cin >> a;
a++;
add(a, i);
}
//cout << "_________" << endl;
dfs1(1,0,1);
//cout << "_________" << endl;
dfs2(1, 1);
//cout << "+++++++++++++++++++++++++++++++++++++++" << endl;
//for (int i = 1; i <= n; i++) {
// cout << id[i] << " ";
//}
//cout << endl;
//cout << endl;
//cout << endl;
//cout << "+++++++++++++++++++++++++++++++++++++++" << endl;
//for (int i = 1; i <= n; i++) {
// cout << son[i] << " ";
//}
//cout << endl;
//cout << endl;
//cout << endl;
build(1, 1, n);
cin >> m;
char op[20];
int x;
while (m--) {
cin >> op >> x;
x++;
if (!strcmp(op, "install")) {
int a = tr[1].sum;
updata(x);
int b = tr[1].sum;
cout << b - a << endl;
}
else {
int a = tr[1].sum;
modify(1, id[x], id[x] + siz[x] - 1, 0);
int b = tr[1].sum;
cout << a - b << endl;
}
}
return 0;
}