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. 素数筛法—时间复杂度O(n)

    请你想出一个算法求出n以内(含n)的所有素数,要求算法的时间复杂度越小越好. 这里介绍一种算法——快速线性素数筛法(欧拉筛法),时间复杂度O(n). 诀窍在于:筛除合数时,保证每个合数只会被它的最小质 ...

  2. web前端 微信支付之H5支付

    一.什么是微信H5支付? 微信,简直是21世纪的社交产品之最.人们的生活已经离不开它,因为它的触角广泛蔓延像一张巨大无形的网,从而让我们的生活更加便捷高效,这款社交工具我们不做过多评价,但是我们要通过 ...

  3. 【MFC系列】MFC快速设置控件文本字体、大小、颜色、背景

    以静态文本为例,分享一下怎么修改文本字体.大小.颜色.背景等参数.其他文本.控件等可参照修改. 1.修改字体.大小 这个很简单,首先在Dlg类中声明一个CFont类型的成员变量: 然后在类的初始化函数 ...

  4. 21.如何将java类对象转化为json字符串

    使用阿里巴巴的fastJson 下载链接: 链接: https://pan.baidu.com/s/1dHjLOm1 密码: rr3w 用法如下: User user = new User(); us ...

  5. Spark2.0机器学习系列之2:基于Pipeline、交叉验证、ParamMap的模型选择和超参数调优

    Spark中的CrossValidation Spark中采用是k折交叉验证 (k-fold cross validation).举个例子,例如10折交叉验证(10-fold cross valida ...

  6. kettle转换添加hbase-output无法获取hbase表

    问题:kettle转换添加hbase-output无法获取hbase表 win本机安装kettle,本机虚拟机三台,root用户安装有jdk.zookeeper.hadoop.hbase kettle ...

  7. CentOS 6下OpenCV的安装与配置

    自己按照网上的教程一步一步来的 http://www.jb51.net/os/RedHat/280309.html 虚拟机环境 CentOS 6.5 内核版本:4.1.14 64位 gcc,gcc 4 ...

  8. list_for_each_entry解析

    双向链表及链表头: 建立一个双向链表通常有一个独立的用于管理链表的链表头,链表头一般是不含有实体数据的,必须用INIT_LIST_HEAD()进行初始化,表头建立以后,就可以将带有数据结构的实体链表成 ...

  9. IOS 此时无法安装XXX

    背景介绍 替一家公司做了企业APP,由于经常需要更新,考虑到上传到APP Store的审核过程,所以当初选定了是用企业证书发布,然后通过网页自动跳转下载APP. 事情原委 昨天下午突然接到客户反馈,I ...

  10. 爬虫——请求库之selenium模块

      阅读目录 一 介绍 二 安装 三 基本使用 四 选择器 五 等待元素被加载 六 元素交互操作 七 其他 八 项目练习 一 介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解 ...