[NOI2015]软件包管理器
Posted qjs12
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOI2015]软件包管理器相关的知识,希望对你有一定的参考价值。
原来NOI也有这样的题啊,而且还和当年HAOI2015上午T2可以说是撞车了,当年HA的省队这道题应该都A了。
// q.c #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define lc o<<1 #define rc o<<1^1 using namespace std; const int M=100000+10; /**************************************************************************************/ struct Edge { int u,v,nex; Edge() {} Edge(int a,int b,int c):u(a),v(b),nex(c) {} }ed[M<<1]; int head[M],cnt; void add_edge(int a,int b) { ed[cnt]=Edge(a,b,head[a]); head[a]=cnt++; ed[cnt]=Edge(b,a,head[b]); head[b]=cnt++; } /**************************************************************************************/ int f[M],dep[M],size[M],son[M]; void dfs1(int u,int fa,int d) { f[u]=fa,size[u]=1,dep[u]=d; int i; Edge e; for(i=head[u];~i;i=ed[i].nex) { e=ed[i]; if(!f[e.v]) { dfs1(e.v,u,d+1); size[u]+=size[e.v]; if(size[e.v]>size[son[u]]||!son[u]) son[u]=e.v; } } } int top[M],id[M],nd[M],dck,LEFT[M]; void dfs2(int u,int TP) { top[u]=TP; LEFT[u]=id[u]=++dck; nd[dck]=u; if(!son[u]) return ; dfs2(son[u],TP); int i; Edge e; LEFT[u]=max(LEFT[u],LEFT[son[u]]); for(i=head[u];~i;i=ed[i].nex) { e=ed[i]; if(e.v!=f[u]&&e.v!=son[u]) { dfs2(e.v,e.v); LEFT[u]=max(LEFT[u],LEFT[e.v]); } } } /**************************************************************************************/ int L[M<<2],R[M<<2],ins[M<<2],uns[M<<2],tag[M<<2]; void build(int o,int l,int r) { L[o]=l,R[o]=r,uns[o]=r-l+1; if(l==r) return ; int mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1,r); } void DOWN(int o) { if(tag[o]==1) { ins[lc]=R[lc]-L[lc]+1,uns[lc]=0,tag[lc]=1; ins[rc]=R[rc]-L[rc]+1,uns[rc]=0,tag[rc]=1; } else { ins[lc]=0,uns[lc]=R[lc]-L[lc]+1,tag[lc]=2; ins[rc]=0,uns[rc]=R[rc]-L[rc]+1,tag[rc]=2; } tag[o]=0; } void UP(int o) { ins[o]=ins[lc]+ins[rc]; uns[o]=uns[lc]+uns[rc]; } int add(int o,int l,int r) { if(l<=L[o]&&R[o]<=r) { int tmp=uns[o]; ins[o]=R[o]-L[o]+1,uns[o]=0,tag[o]=1; return tmp; } else { if(tag[o]) DOWN(o); int mid=(L[o]+R[o])>>1,ans=0; if(l<=mid) ans+=add(lc,l,r); if(r>mid) ans+=add(rc,l,r); UP(o); return ans; } } int sub(int o,int l,int r) { if(l<=L[o]&&R[o]<=r) { int tmp=ins[o]; ins[o]=0,uns[o]=R[o]-L[o]+1,tag[o]=2; return tmp; } else { if(tag[o]) DOWN(o); int mid=(L[o]+R[o])>>1,ans=0; if(l<=mid) ans+=sub(lc,l,r); if(r>mid) ans+=sub(rc,l,r); UP(o); return ans; } } /**************************************************************************************/ int install(int a,int b) { int ans=0; while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) swap(a,b); ans+=add(1,id[top[a]],id[a]); a=f[top[a]]; } if(dep[a]>dep[b]) swap(a,b); return ans+add(1,id[a],id[b]); } int unstall(int a) { int ans=0; ans=sub(1,id[a],LEFT[a]); return ans; } /**************************************************************************************/ int main() { freopen("manager.in","r",stdin); freopen("manager.out","w",stdout); int n,q,a; char str[17]; scanf("%d",&n); memset(head,-1,sizeof(head)); for(int i=1;i<n;i++) { scanf("%d",&a); add_edge(i+1,a+1); } dfs1(1,-1,0); dfs2(1,1); build(1,1,dck); scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%s%d",str,&a); ++a; if(str[0]==‘i‘) printf("%d\n",install(1,a)); else printf("%d\n",unstall(a)); } return 0; }
以上是关于[NOI2015]软件包管理器的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4196 [Noi2015]软件包管理器——树链剖分
Bzoj 4196: [Noi2015]软件包管理器 树链剖分