[NOI2015]软件包管理器(树链剖分,线段树)
题目描述
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,……,A[m-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步操作中改变安装状态的软件包数。
思路:
显然的一道树剖裸题
对于安装操作,我们要做的就是查询到根节点的路径上有几个0
并路径覆盖为1
对于卸载操作
我们要做的就是查询以该点为根的子树内有多少个1
并完成子树赋值为0
暴力上树剖即可
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<bitset> #include<queue> #include<algorithm> #define int long long #define rii register int i #define rij register int j using namespace std; int n,q; struct ljb{ int to,nxt; }x[400005]; struct node{ int val,lazy; }y[600005]; int f[200005],sd[200005],head[200005],size[200005]; int weison[200005],cnt,bnt,nid[200005],ntop[200005]; int res; void add(int from,int to) { cnt++; x[cnt].to=to; x[cnt].nxt=head[from]; head[from]=cnt; } void dfs1(int wz,int fa,int s) { sd[wz]=s; f[wz]=fa; size[wz]=1; int maxn=0; for(rii=head[wz];i!=0;i=x[i].nxt) { int to=x[i].to; if(to==fa) { continue; } dfs1(to,wz,s+1); size[wz]+=size[to]; if(size[to]>maxn) { maxn=size[to]; weison[wz]=to; } } } void dfs2(int wz,int top) { bnt++; nid[wz]=bnt; ntop[wz]=top; if(weison[wz]==0) { return; } dfs2(weison[wz],top); for(rii=head[wz];i!=0;i=x[i].nxt) { int to=x[i].to; if(weison[wz]==to||f[wz]==to) { continue; } dfs2(to,to); } } void pushdown(int bh,int cd) { y[bh*2].lazy=y[bh].lazy; y[bh*2+1].lazy=y[bh].lazy; y[bh*2].val=y[bh].lazy*(cd-(cd/2)); y[bh*2+1].val=y[bh].lazy*(cd/2); y[bh].lazy=-1; } void updata(int bh,int nl,int nr,int l,int r,int val) { int len=(nr-nl+1); if(l<=nl&&nr<=r) { y[bh].lazy=val; y[bh].val=val*len; return; } if(y[bh].lazy!=-1) { pushdown(bh,len); } int mid=(nl+nr)/2; if(l<=mid) { updata(bh*2,nl,mid,l,r,val); } if(r>mid) { updata(bh*2+1,mid+1,nr,l,r,val); } y[bh].val=(y[bh*2].val+y[bh*2+1].val); } void query(int bh,int nl,int nr,int l,int r) { if(l<=nl&&r>=nr) { res+=y[bh].val; return; } int mid=(nl+nr)/2; if(y[bh].lazy!=-1) { pushdown(bh,nr-nl+1); } if(l<=mid) { query(bh*2,nl,mid,l,r); } if(r>mid) { query(bh*2+1,mid+1,nr,l,r); } } int querylj(int from,int to) { int ans=0; while(ntop[from]!=ntop[to]) { if(sd[ntop[from]]<sd[ntop[to]]) { swap(from,to); } res=0; query(1,1,n,nid[ntop[from]],nid[from]); ans+=res; from=f[ntop[from]]; } if(sd[from]>sd[to]) { swap(from,to); } res=0; query(1,1,n,nid[from],nid[to]); ans+=res; return ans; } void addlj(int from,int to,int val) { while(ntop[from]!=ntop[to]) { if(sd[ntop[from]]<sd[ntop[to]]) { swap(from,to); } updata(1,1,n,nid[ntop[from]],nid[from],val); from=f[ntop[from]]; } if(sd[from]>sd[to]) { swap(from,to); } updata(1,1,n,nid[from],nid[to],val); } void addson(int wz,int val) { updata(1,1,n,nid[wz],nid[wz]+size[wz]-1,val); } int queryson(int wz) { res=0; query(1,1,n,nid[wz],nid[wz]+size[wz]-1); return res; } signed main() { scanf("%lld",&n); for(rii=1;i<=400000;i++) { y[i].lazy=-1; } for(rii=2;i<=n;i++) { int yl; scanf("%lld",&yl); add(i,yl+1); add(yl+1,i); } dfs1(1,0,1); dfs2(1,1); scanf("%lld",&q); for(rii=1;i<=q;i++) { int from; string s; char c=getchar(); while(c<'a'||c>'z') { c=getchar(); } while(c>='a'&&c<='z') { s+=c; c=getchar(); } if(s=="install") { scanf("%lld",&from); from++; int ltt=querylj(1,from); printf("%lld\n",sd[from]-ltt); addlj(1,from,1); } if(s=="uninstall") { scanf("%lld",&from); from++; int ltt=queryson(from); printf("%lld\n",ltt); addson(from,0); } // res=0; // query(1,1,n,nid[1],nid[1]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[2],nid[2]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[3],nid[3]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[4],nid[4]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[5],nid[5]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[6],nid[6]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[7],nid[7]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[8],nid[8]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[9],nid[9]); // cout<<res<<" "; // res=0; // query(1,1,n,nid[10],nid[10]); // cout<<res<<endl; } }