问题描述

    Linux用户和OS X用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其他软件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的是yum,以及OS X下可用的homebrew都是优秀的软件包管理器。你决定设计你自己的软件包管理器。不可避免的,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包B以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m>=2)个软件包A1,A2,A2依赖A3,...,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,Am-1依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。

输入格式

    /*从manager.in中读入数据。*/输入文件的第1行包含1个整数n,表示软件包的总数。软件包从0开始编号。随后一行包含n-1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,...,n-2,n-1号软件包依赖的软件包编号。接下来一行包含1个整数q,表示询问的总数。之后的q行,每行1个询问。询问分为两种:●install x:表示安装软件包x●uninstall x:表示卸载软件包x你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态,对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。

输出格式

    /*输出到文件manager.out中。*/输出文件包括q行。输出文件的第i行输出1个整数,为第i步操作中改变安装状态的软件包数。

样例输入1:
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0

样例输入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
样例输出

样例输出1:
3
1
3
2
3

样例输出2:
1
3
2
1
3
1
1
1
0
1

题解

树链剖分+DFS序。安装从当前节点到根节点的软件包直接用树剖处理。
由于树剖也是在DFS的过程中实现的,寻找轻重链只是改变了子节点遍历的顺序,一棵子树仍然可以用DFS序转化成一个区间,因此卸载操作直接用DFS序+线段树处理即可。

代码

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e5+5;
int a,n,q,cnt,tot,Last[maxn];
int l[maxn],r[maxn],id[maxn],fa[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn],maxx[maxn];
string op;
struct node{int sum,lazy;
}tree[8*maxn];
struct node_{int Next,End;
}edge[maxn];
inline int input()
{char t=getchar();int x=0,flag=0;while(t<48||t>57){if(t=='-') flag=1;t=getchar();}for(;t>=48&&t<=57;t=getchar()) x=x*10+t-48;return flag?-x:x;
}
inline void output(int x)
{if(x<0) putchar('-'),x=-x;if(x>9) output(x/10);putchar(x%10+48);
}
void save(int x,int y)
{edge[++cnt].End=y;edge[cnt].Next=Last[x],Last[x]=cnt;
}
void getsiz(int x,int f)
{siz[x]=1,fa[x]=f,dep[x]=dep[fa[x]]+1;int temp=Last[x];while(temp){int y=edge[temp].End;getsiz(y,x),siz[x]+=siz[y];if(siz[y]>maxx[x]) maxx[x]=siz[y],son[x]=y;temp=edge[temp].Next;}
}
void getway(int x,int anc)
{if(!x) return;l[x]=id[x]=++tot,top[x]=anc,getway(son[x],anc);int temp=Last[x];while(temp){int y=edge[temp].End;if(y!=son[x]) getway(y,y);temp=edge[temp].Next;}r[x]=tot;
}
void build(int p,int ll ,int rr)
{tree[p].sum=0,tree[p].lazy=-1;if(ll<rr){int mid=(ll+rr)>>1;build(p<<1,ll,mid),build(p<<1|1,mid+1,rr);}
}
void putdown(int p,int ll,int rr)
{if(ll==rr) return;int mid=(ll+rr)>>1;tree[p<<1].lazy=tree[p].lazy;tree[p<<1].sum=(mid-ll+1)*tree[p].lazy;tree[p<<1|1].lazy=tree[p].lazy;tree[p<<1|1].sum=(rr-mid)*tree[p].lazy;tree[p].lazy=-1;
}
int getsum(int p,int ll,int rr,int x,int y)
{if(tree[p].lazy!=-1) putdown(p,ll,rr);if(ll>=x&&rr<=y) return tree[p].sum;int mid=(ll+rr)>>1,lsum=0,rsum=0;if(x<=mid&&y>=ll) lsum+=getsum(p<<1,ll,mid,x,y);if(y>mid&&x<=rr) rsum+=getsum(p<<1|1,mid+1,rr,x,y);return lsum+rsum;
}
void modify(int p,int ll,int rr,int x,int y,int t)
{if(tree[p].lazy!=-1) putdown(p,ll,rr);if(ll>=x&&rr<=y){tree[p].lazy=t;tree[p].sum=(rr-ll+1)*tree[p].lazy;return;}int mid=(ll+rr)>>1;if(x<=mid&&y>=ll) modify(p<<1,ll,mid,x,y,t);if(y>mid&&x<=rr) modify(p<<1|1,mid+1,rr,x,y,t);tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}
int query(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(dep[top[x]]>dep[top[y]]) swap(x,y);ans+=getsum(1,1,tot,id[top[y]],id[y]);y=fa[top[y]];}if(dep[x]>dep[y]) swap(x,y);ans+=getsum(1,1,tot,id[x],id[y]);return ans;
}
void change(int x,int y)
{while(top[x]!=top[y]){if(dep[top[x]]>dep[top[y]]) swap(x,y);modify(1,1,tot,id[top[y]],id[y],1);y=fa[top[y]];}if(dep[x]>dep[y]) swap(x,y);modify(1,1,tot,id[x],id[y],1);
}
int main()
{n=input();for(int i=2;i<=n;i++) a=input()+1,save(a,i);getsiz(1,0),getway(1,1),build(1,1,tot);q=input();while(q--){cin>>op,a=input()+1;if(op=="install"){output(dep[a]-query(1,a)),putchar('\n');change(1,a);}else{output(getsum(1,1,tot,l[a],r[a])),putchar('\n');modify(1,1,tot,l[a],r[a],0);}}return 0;
}

【NOI2015 Day1】软件包管理器相关推荐

  1. 【NOI2015】软件包管理器

    NOI难得的水题,话说还是T2诶--又学到了线段树的一种新的魔性使用 看sxysxy大神的代码才写出来的,sxysxy_orz 原题: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包 ...

  2. NOI2015 Day1 T2 软件包管理器 树链剖分

    NKOJ3423 NOI2015 软件包管理器 时间限制 : 20000 MS 空间限制 : 524288 KB 问题描述 Linux用户和OS X用户一定对软件包管理器不会陌生.通过软件包管理器,你 ...

  3. [NOI2015]软件包管理器

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

  4. P2146 [NOI2015] 软件包管理器

    P2146 [NOI2015] 软件包管理器 题意: 如果软件包 a 依赖软件包 b,那么安装软件包 a 以前,必须先安装软件包 b.同时,如果想要卸载软件包 b,则必须卸载软件包 a. 软件包之间存 ...

  5. 洛谷P2146DTOJ2409 [NOI2015]软件包管理器

    洛谷P2146&&DTOJ2409 [NOI2015]软件包管理器 题目 题目描述 输入格式 输出格式 样例 样例输入1 样例输出1 样例输入2 样例输出2 数据范围与提示 样例1说明 ...

  6. BZOJ4196:[NOI2015]软件包管理器——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=4196 https://www.luogu.org/problemnew/show/P2146 你决定 ...

  7. BZOJ4196[Noi2015]软件包管理器——树链剖分+线段树

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

  8. bzoj4196:[Noi2015]软件包管理器

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

  9. helm部署仓库中没有的包_Kubernetes的Helm软件包管理器简介

    helm部署仓库中没有的包 Before we dive into the Helm package manager, I'm going to explain some key concepts t ...

最新文章

  1. 报名 | 工业大数据分析:机会与挑战讲座
  2. ISA Server***检测及配置
  3. Linux系统新建用户用ssh远程登陆显示-bash-4.1$
  4. SLAM的评价指标、真实值、估计值及误差分析(转)
  5. JavaScript实现depth First Search深度优先搜索算法(附完整源码)
  6. 【UOJ188】 Sanrd【类min_25筛】
  7. 【转】1.C Task.CompletedTask和Task.Result小记
  8. 马斯克:特斯拉FSD测试版V9将再推迟一周
  9. 一千万条数据去重_simhash算法:海量千万级的数据去重
  10. mysql unable to find_centos8.2安装mysql8.0时报错Error:Unable to find a match: mysql-community-server...
  11. 如何将一个java程序变成exe_如何将一个java程序转换为.exe文件?
  12. Web之路笔记之三 - 使用Floating实现双栏样式
  13. 如何实现百万TPS?详解JMQ4的存储设计
  14. Sql查询出数据表中所有重复的数据
  15. python里字典的基本用法(包括嵌套字典)_Python使用字典的嵌套功能详解 python 嵌套中的字典赋值...
  16. 2021-05-06
  17. LLC谐振参数计算实例,mathcad格式,列出完整计算公式,软件自动计算并绘出增益曲线,方便修改设计参数
  18. matlab一维otsu算法,[转载]matlab graythresh()函数(Otsu算法)
  19. 阿铭Linux_传统IDC 部署网站学习笔记20190118
  20. java当前时间减一年_Java获取时间,将当前时间减一年,减一天,减一个月

热门文章

  1. ps——油漆字体效果
  2. 安卓调用系统组件实现拨打电话
  3. Java代码走查审查规范总结
  4. 【Linux】误删libc提示Kernel panic not syncing: Attempted to kill init解决办法
  5. 中止执行后超过2年_超过两年是否可以申请强制执行
  6. 我可以在iPad上使用WhatsApp吗?
  7. 深度学习系列笔记之统计基础
  8. 7-33 统计素数并求和 (20 分)
  9. 微信和支付宝相关支付业务场景介绍
  10. 英特尔重入代工行业的底气和挑战,台积电,三星有点慌。