NOI 2015 d1t2 洛谷 【P2146】 软件包管理器
2015-12-09 21:09
190 查看
Linux用户和OSX用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。ebian/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,……,A[m-1]依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。
输入输出格式 Input/output
输入格式:
从文件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步操作中改变安装状态的软件包数。
输入输出样例 Sample input/output
样例测试点#1 输入样例: 在线IDE
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0
输出样例:
3
1
3
2
3
裸树剖
你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m≥2)个软件包A1,A2,A3,⋯,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,A[m-1]依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。
输入输出格式 Input/output
输入格式:
从文件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步操作中改变安装状态的软件包数。
输入输出样例 Sample input/output
样例测试点#1 输入样例: 在线IDE
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0
输出样例:
3
1
3
2
3
#include<iostream> #include<stdio.h> #include<vector> #define lson (id*2) #define rson (id*2+1) #include<string.h> #define clr(p) memset(p,-1,sizeof(p)) using namespace std; struct node{ int val,lazy; }tree[800005]; vector<int> lin[100005]; int son[100005]; int top[100005]; int size[100005]; int fa[100005]; int in[100005]; int dep[100005]; int out[100005]; int n; int tot=0; int m; int abs(int x) { if(x<0) return -x; return x; } void dfs1(int x,int pre) //size and son,dep; { fa[x]=pre; son[x]=-1; size[x]=1; for(int i=0;i<lin[x].size();i++) { int v=lin[x][i]; if(v==pre) continue; dep[v]=dep[x]+1; dfs1(v,x); if(son[x]==-1||size[son[x]]<size[v]) son[x]=v; size[x]+=size[v]; } } void dfs2(int x,int pre,int id) //son is direct son that shares the same top id; { top[x]=id; in[x]=++tot; if(son[x]!=-1) dfs2(son[x],x,id); for(int i=0;i<lin[x].size();i++) { int v=lin[x][i]; if(v==pre) continue; if(son[x]==v) continue; dfs2(v,x,v); } out[x]=tot; } void push_up(int id) { tree[id].val=tree[lson].val+tree[rson].val; } void push_down(int id,int l,int mid,int r) //usage of lazy; { if(tree[id].lazy==-1) return ; tree[lson].lazy=tree[rson].lazy=tree[id].lazy; tree[lson].val=(mid-l+1)*tree[id].lazy; tree[rson].val=(r-mid)*tree[id].lazy; tree[id].lazy=-1; } void add(int id,int l,int r,int L,int R,int V) { if(l>R||r<L) return ; if(l>=L&&r<=R) { tree[id].val=0; if(V==1) tree[id].val=r-l+1; tree[id].lazy=V; return ; } int mid=(l+r)>>1; push_down(id,l,mid,r); add(lson,l,mid,L,R,V); add(rson,mid+1,r,L,R,V); push_up(id); } void _down(int x) //the containing tree; { int ans=tree[1].val; add(1,1,n,in[x],out[x],0); printf("%d\n",abs(ans-tree[1].val)); } void _up(int x,int y) //a chain from(x to y) { int ans=tree[1].val; while(top[x]!=top[y]) //use depth to deal { if(dep[top[x]]<dep[top[y]]) swap(x,y); //!!! add(1,1,n,in[top[x]],in[x],1); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); //!!! add(1,1,n,in[x],in[y],1); printf("%d\n",abs(ans-tree[1].val)); } void solve() { for(int i=1;i<=m;i++) { char a[10]; scanf("%s",a); int aa; scanf("%d",&aa); aa++; if(a[0]=='i') _up(1,aa); if(a[0]=='u') _down(aa); } } int main() { scanf("%d",&n); for(int i=1;i<+n;i++) tree[i].lazy=-1; for(int i=2;i<=n;i++) { int aa; scanf("%d",&aa); aa++; lin[i].push_back(aa); lin[aa].push_back(i); } dep[1]=1; dfs1(1,0); dfs2(1,0,1); scanf("%d",&m); solve(); }
裸树剖
相关文章推荐
- 哈密顿环之深度优先
- Android测试
- listview优化
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- malloc源码分析---4
- 【Android】将图片转换为圆角
- Volley框架之二 基本流程
- SQL注入攻击与防御学习笔记一
- Putty和Xming创建远程GUI的SSH连接
- python拾遗(一)前言
- ECMAScript 引用类型
- Win10下VMWare正常使用,但Win10 Update后出现无法启动问题的解决方法
- java中的基本jdbc中mvc基本示例
- hadoop(2.x)以hadoop2.2为例完全分布式最新高可靠安装文档
- Android面试必问的Listview getview方法问题
- 双机或者多机同步
- hoj5586 区间和最大
- osmf 学习笔记
- 垃圾回收器GC
- LNMP之Nginx