#128. 【NOI2015】软件包管理器
Linux 用户和 OS X 用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。Debian/Ubuntu 使用的 apt-get,Fedora/CentOS 使用的 yum,以及 OS X 下可用的 homebrew 都是优秀的软件包管理器。
你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包 依赖软件包 ,那么安装软件包 以前,必须先安装软件包 。同时,如果想要卸载软件包 ,则必须卸载软件包 。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除 号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而 号软件包不依赖任何一个软件包。依赖关系不存在环(若有 个软件包 ,其中 依赖 , 依赖 , 依赖 ,……, 依赖 ,而 依赖 ,则称这 个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为 。
输入格式
输入文件的第 行包含 个正整数 ,表示软件包的总数。软件包从 开始编号。
随后一行包含 个整数,相邻整数之间用单个空格隔开,分别表示 号软件包依赖的软件包的编号。
接下来一行包含 个正整数 ,表示询问的总数。
之后 行,每行 个询问。询问分为两种:
- install :表示安装软件包
- uninstall :表示卸载软件包
你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。
输出格式
输出文件包括 行。
输出文件的第 行输出 个整数,为第 步操作中改变安装状态的软件包数。
样例一
input
7 0 0 0 1 1 5 5 install 5 install 6 uninstall 1 install 4 uninstall 0
output
3 1 3 2 3
explanation
一开始所有的软件包都处于未安装状态。
安装 号软件包,需要安装 三个软件包。
之后安装 号软件包,只需要安装 号软件包。此时安装了 四个软件包。
卸载 号软件包需要卸载 三个软件包。此时只有 号软件包还处于安装状态。
之后安装 号软件包,需要安装 两个软件包。此时 处在安装状态。
最后,卸载 号软件包会卸载所有的软件包。
样例二
input
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
output
1 3 2 1 3 1 1 1 0 1
样例三
见样例数据下载。
限制与约定
测试点编号 | 的规模 | 的规模 | 备注 |
---|---|---|---|
1 | |||
2 | |||
3 | 数据不包含卸载操作 | ||
4 | |||
5 | 编号为
的软件包所依赖的软件包编号在
内均匀随机。 每次执行操作的软件包编号在 内均匀随机。 |
||
6 | |||
7 | |||
8 | |||
9 | |||
10 | |||
11 | |||
12 | |||
13 | |||
14 | |||
15 | |||
16 | |||
17 | |||
18 | |||
19 | |||
20 |
时间限制:
空间限制:
思路&&分析
这题,我们用0表示一个软件没有被下载,1表示已经被下载。这题一共有两个操作,我们很容易看出操作uninstall x是把以x为根的子树的所有已经install过的软件给卸载掉,就是把x和他子树的值全都赋为0;而操作install x则可以看做是把从根到x的路径上的所有软件包(包括x)全都给下载下来,就是对一条路径上的所有点赋值1。简要分析过后我们就可以发现这是道树剖裸题,只要用线段树维护所有的值就行了。对于答案,我们在每次修改前记录一下根的sum,然后sum与操作后根的sum的绝对值就是答案了。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>inline void read(T &x) {
x=0;T f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
#define rd(x) read(x)
#define r2(x,y) rd(x),rd(y)
#define r3(x,y,z) r2(x,y),rd(z)
#define r4(x,y,z,o) r2(x,y),r2(z,o)
#define ls o<<1
#define rs o<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn=1000010;
int n,q,fa[maxn],dep[maxn],tp[maxn],son[maxn],id[maxn],dfs_clock,sz[maxn];
vector<int>G[maxn];
struct Seg {
int sum,upd;
inline void init() {
sum=0;
upd=-1;
}
}t[maxn<<2];
inline void pushup(int o) {
t[o].sum=t[ls].sum+t[rs].sum;
}
inline void pushdown(int o,int l,int r) {
if(t[o].upd!=-1) {
int mid=(l+r)>>1;
t[ls].sum=t[o].upd*(mid-l+1);
t[rs].sum=t[o].upd*(r-mid);
t[ls].upd=t[rs].upd=t[o].upd;
t[o].upd=-1;
}
}
inline void dfs1(int u) {
sz[u]=1;
for(unsigned i=0;i<G[u].size();i++) {
int v=G[u][i];
if(v==fa[u])
continue;
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
sz[u]+=sz[v];
if(!son[u]||sz[son[u]]<sz[v])
son[u]=v;
}
}
inline void dfs2(int u,int p) {
id[u]=++dfs_clock;
tp[u]=p;
if(!son[u])
return;
dfs2(son[u],p);
for(unsigned i=0;i<G[u].size();i++) {
int v=G[u][i];
if(v==fa[u]||v==son[u])
continue;
dfs2(v,v);
}
}
inline void build(int o,int l,int r) {
t[o].init();
if(l==r)
return;
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(o);
}
inline void upset(int o,int l,int r,int ql,int qr,int s) {
pushdown(o,l,r);
if(l==ql&&r==qr) {
//cout<<o<<" "<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<s<<" "<<t[o].sum<<" "<<t[o].upd<<endl;
t[o].sum=s*(r-l+1);
t[o].upd=s;
//cout<<o<<" "<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<s<<" "<<t[o].sum<<" "<<t[o].upd<<endl;
return;
}
int mid=(l+r)>>1;
if(qr<=mid)
upset(lson,ql,qr,s);
else if(ql>mid)
upset(rson,ql,qr,s);
else {
upset(lson,ql,mid,s);
upset(rson,mid+1,qr,s);
}
pushup(o);
}
inline void subset1(int x) {
upset(1,1,n,id[x],id[x]+sz[x]-1,0);
}
inline void subset2(int x) {
//cout<<"Do install:"<<x<<endl;
while(tp[x]!=1) {
//cout<<"Do install:"<<x<<" "<<tp[x]<<" "<<id[x]<<" "<<id[tp[x]]<<endl;
upset(1,1,n,id[tp[x]],id[x],1);
x=fa[tp[x]];
}
//cout<<"Do install:"<<x<<endl;
upset(1,1,n,1,id[x],1);
}
int main() {
rd(n);
for(int i=2,x;i<=n;i++) {
rd(x);x++;
G[x].push_back(i);
G[i].push_back(x);
}
dep[1]=1;fa[1]=-1;
dfs1(1);
dfs2(1,1);
build(1,1,n);
/*for(int i=1;i<=n;i++)
cout<<sz[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++)
cout<<tp[i]<<" ";
cout<<endl;*/rd(q);
while(q--) {
char s[100];int x;
scanf("%s",s+1);rd(x);x++;
int res=t[1].sum;
if(s[1]=='u') {
subset1(x);//cout<<"uninstall :"<<res<<" "<<t[1].sum<<endl;
printf("%d\n",abs(res-t[1].sum));
}
else {
subset2(x);//cout<<"install :"<<res<<" "<<t[1].sum<<endl;
printf("%d\n",abs(res-t[1].sum));
}
}
}