Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 412  Solved: 251
[Submit][Status][Discuss]

Description

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依赖A3,A3依赖A4,……,Am−1依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。
 

Input

输入文件的第1行包含1个正整数n,表示软件包的总数。软件包从0开始编号。

随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,…,n−2,n−1号软件包依赖的软件包的编号。
接下来一行包含1个正整数q,表示询问的总数。
之后q行,每行1个询问。询问分为两种:
installx:表示安装软件包x
uninstallx:表示卸载软件包x
你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。
n=100000 q=100000

Output

输出文件包括q行。

输出文件的第i行输出1个整数,为第i步操作中改变安装状态的软件包数。
 

Sample Input

7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0

Sample Output

3
1
3
2
3

HINT

一开始所有的软件包都处于未安装状态。

安装 5 号软件包,需要安装 0,1,5 三个软件包。
之后安装 6 号软件包,只需要安装 6 号软件包。此时安装了 0,1,5,6 四个软件包。
卸载 1 号软件包需要卸载 1,5,6 三个软件包。此时只有 0 号软件包还处于安装状态。
之后安装 4 号软件包,需要安装 1,4 两个软件包。此时 0,1,4 处在安装状态。
最后,卸载 0 号软件包会卸载所有的软件包。
 
题解:
  显然的树链剖分,初始时树上所有结点权值均为0;1操作将根到x结点的所有结点权值置为1,并输出这次修改了多少个元素;2操作将x结点的子树中所有结点权值置为0,并输出这次修改了多少个元素。
  注意打标记的时候不应该是累计,即标记传递的时候不是 son.lazy+=fa.lazy 而是 son.lazy=fa,lazy,因为每个节点只存在0和1两种状态
 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=;
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int N,M;
int dep[maxn],siz[maxn],fa[maxn],son[maxn],top[maxn],id[maxn];
int val[maxn];
int num;
char s[];
vector<int> to[maxn];
inline void dfs1(int rt,int fath,int deep){
dep[rt]=deep; siz[rt]=; son[rt]=; fa[rt]=fath;
for(int i=;i<to[rt].size();i++){
int y=to[rt][i];
if(y!=fa[rt]){
dfs1(y,rt,deep+);
siz[rt]+=siz[y];
if(siz[son[rt]]<siz[y]){
son[rt]=y;
}
}
}
}
inline void dfs2(int rt,int tp){
top[rt]=tp;
id[rt]=++num;
if(son[rt]!=) dfs2(son[rt],tp);
for(int i=;i<to[rt].size();i++){
int y=to[rt][i];
if(y!=fa[rt]&&y!=son[rt]){
dfs2(y,y);
}
}
} struct Tree{
int l,r,sum,lazy;
}tree[maxn*];
inline void build(int rt,int l,int r){
tree[rt].l=l; tree[rt].r=r;
if(l==r){
tree[rt].sum=;
tree[rt].lazy=;
return ;
}
int mid=(l+r)>>;
build(rt<<,l,mid); build(rt<<|,mid+,r);
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
}
inline void update_son(int rt){
int d=tree[rt].lazy;
if(d!=){
tree[rt<<].sum+=(tree[rt<<].r-tree[rt<<].l+)*d;
if(tree[rt<<].sum<) tree[rt<<].sum=;
if(tree[rt<<].sum>(tree[rt<<].r-tree[rt<<].l+))
tree[rt<<].sum=(tree[rt<<].r-tree[rt<<].l+);
tree[rt<<|].sum+=(tree[rt<<|].r-tree[rt<<|].l+)*d;
if(tree[rt<<|].sum<) tree[rt<<|].sum=;
if(tree[rt<<|].sum>(tree[rt<<|].r-tree[rt<<|].l+))
tree[rt<<|].sum=(tree[rt<<|].r-tree[rt<<|].l+);
tree[rt<<].lazy=tree[rt].lazy; tree[rt<<|].lazy=tree[rt].lazy;
tree[rt].lazy=;
}
}
inline void change(LL rt,LL l,LL r,LL delta){
if(l<=tree[rt].l&&tree[rt].r<=r){
tree[rt].sum+=(tree[rt].r-tree[rt].l+)*delta;
if(tree[rt].sum<) tree[rt].sum=;
if(tree[rt].sum>(tree[rt].r-tree[rt].l+)) tree[rt].sum=(tree[rt].r-tree[rt].l+);
tree[rt].lazy=delta;
return ;
}
update_son(rt);
LL mid=(tree[rt].l+tree[rt].r)>>;
if(l<=mid) change(rt<<,l,r,delta);
if(mid+<=r) change(rt<<|,l,r,delta);
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
} inline LL query(LL rt,LL l,LL r){
if(l<=tree[rt].l&&tree[rt].r<=r){
return tree[rt].sum;
}
update_son(rt);
LL ans=;
LL mid=(tree[rt].l+tree[rt].r)>>;
if(l<=mid) ans+=query(rt<<,l,r);
if(mid+<=r) ans+=query(rt<<|,l,r);
return ans;
}
inline void ASK(int u,int v){
int tp1=top[u],tp2=top[v];
int ans=,tmpv=v;
if(u==-){//卸载
ans=query(,id[v],id[v]);
if(ans==){
ans=query(,id[v],id[v]+siz[v]-);//子树权值之和
printf("%d\n",ans);
change(,id[v],id[v]+siz[v]-,-);
}
else printf("0\n");
}
else{//安装
ans=query(,id[v],id[v]);
if(ans==){
while(tp1!=tp2){
if(dep[tp1]<dep[tp2]){
swap(tp1,tp2);
swap(u,v);
}
ans+=query(,id[tp1],id[u]);
change(,id[tp1],id[u],);
u=fa[tp1],tp1=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
ans+=query(,id[u],id[v]);
ans=dep[tmpv]-ans;
change(,id[u],id[v],);
printf("%d\n",ans);
}
else printf("0\n");
}
}
int main(){
N=read();
for(int i=,u;i<=N;i++){
u=read(); u++;
to[u].push_back(i); to[i].push_back(u);
}
dfs1(,,); dfs2(,);
build(,,num);
M=read();
for(int i=,x;i<=M;i++){
scanf("%s%d",s,&x);
x++;
if(s[]=='i'){
ASK(,x);
}
else if(s[]=='u'){
ASK(-,x);
}
}
return ;
}

  现再提供造数据的程序(根据需要调数据范围),给那些死都调不出来的小伙伴们。。。

#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("makedata.out","w",stdout);
srand(time());
int N,M;
N=rand()%+;
cout<<N<<endl;
for(int i=;i<=N-;i++){
int to=rand()%i;
cout<<to<<" ";
}
cout<<endl;
M=rand()%+;
cout<<M<<endl;
for(int i=;i<=M;i++){
int kin=rand()%;
if(kin==) cout<<"install"<<" ";
else cout<<"uninstall"<<" ";
cout<<rand()%N<<endl;
}
return ;
}

4196: [Noi2015]软件包管理器的更多相关文章

  1. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  2. Bzoj 4196: [Noi2015]软件包管理器 树链剖分

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Statu ...

  3. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  4. bzoj 4196: [Noi2015]软件包管理器

    Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...

  5. 4196. [NOI2015]软件包管理器【树链剖分】

    Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...

  6. 【刷题】BZOJ 4196 [Noi2015]软件包管理器

    Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...

  7. [BZOJ4196][NOI2015]软件包管理器

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1040  Solved: 603[Submit][Stat ...

  8. [BZOJ4196][NOI2015]软件包管理器(树链剖分)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2166  Solved: 1253[Submit][Sta ...

  9. [NOI2015]软件包管理器

    4621 [NOI2015]软件包管理器  题目等级 : 钻石 Diamond   题目描述 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过 ...

随机推荐

  1. 170413、怎么精确理解leader布置的任务(技术外的话)

    [缘起] 和一个同学交代了一个很重要的事情,结果执行的结果并不是自己想要的,微微生气之余,简单的聊聊“如何精确的理解leader布置的任务”. [员工角度的潜在困惑] 1)leader讲了很多,脑子记 ...

  2. Python--上传文件和下载文件

    #!/usr/bin/env python# -*- coding: utf-8 -*-# @Time : 2017/12/28 13:56# @Author : Aries# @Site : # @ ...

  3. vim简单的配置

    "设置当文件被改动时自动载入 set autoread "在左侧行号 set nu "tab长度为4 "覆盖文件时不备份 set nobackup " ...

  4. Program terminated with signal SIGABRT, Aborted.

    linux C++ 程序 启动后就奔溃 #0 0x00007f01ee4c21f7 in raise () from /lib64/libc.so.6 #1 0x00007f01ee4c38e8 in ...

  5. crontab下设置ntpdate的问题

    1.在crontab里设置了ntpdate 同步时间,一段时间发现没有起作用 原来的写法是 20 00 × × × ntpdate cn.pool.ntp.org 单独拿出来执行也是没问题的,最近好好 ...

  6. windows 下 方便工作的bat文件批处理命令

    1.删除目录下 不包含某串字符的文件: @echo offfor /f "delims=" %%a in ('dir /s /a-d/b *.mp3') do ( echo &qu ...

  7. Mybatis框架学习总结-解决字段名与实体类属性名不相同的冲突

    在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定是完全相同的. 1.准备演示需要使用的表和数据 CREATE TABLE orders( order_id INT PRIMARY KEY ...

  8. Spark2.0机器学习系列之10: 聚类(高斯混合模型 GMM)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  9. w命令

    命 令:w 功能说明:显示目前登入系统的用户信息. 语 法:w [-fhlsuV][用户名称] 补充说明:执行这项指令可得知目前登入系统的用户有那些人,以及他们正在执行的程序.单独执行w 指令会显示所 ...

  10. vue 动画过渡

    一.过渡(动画) 1. 简介 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果,本质上还是使用CSS3动画:transition.animation 2. 基本用法 1.使用t ...