[NOI2015]软件包管理器
题目:BZOJ4196、洛谷P2146、codevs4621、UOJ#128。
题目大意:有一些软件,编号0~n,它们之间有依赖关系,装编号为ai软件先要装编号为i的软件(编号为0的除外),卸载编号为i的软件必须先卸载编号为ai的软件(编号为0的除外)。它们的关系形成树形图。现在有m个任务,每次让你下载或卸载一个软件,问你本次操作一共新下载/卸载了多少软件。
解题思路:树链剖分。用线段树维护每个节点。
对于下载任务,就是将节点0到p修改成1,并统计修改了多少,对每条经过的链区间修改查询即可。
对于卸载任务,就是将以p为根的子树中所有节点修改为0,并统计修改了多少,对整个子树的区间修改查询即可。
C++ Code:
#include<cstdio>
#include<cctype>
#include<cstring>
#define N 100005
#define mem(a) memset(&a,0,sizeof a)
int n,fa[N],sz[N],head[N],cnt,son[N],dep[N],idx,dfn[N],d[N<<2],tag[N<<2],top[N];
struct edge{
int to,nxt;
}e[N<<1];
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
void dfs(int now){
sz[now]=1;
for(int i=head[now];i;i=e[i].nxt)
if(!dep[e[i].to]){
dep[e[i].to]=dep[now]+1;
dfs(e[i].to);
sz[now]+=sz[e[i].to];
if(!son[now]||sz[e[i].to]>sz[son[now]])son[now]=e[i].to;
}
}
void dfs2(int now){
dfn[now]=++idx;
if(son[now])top[son[now]]=top[now],dfs2(son[now]);
for(int i=head[now];i;i=e[i].nxt)
if(dep[now]<dep[e[i].to]&&e[i].to!=son[now])
dfs2(top[e[i].to]=e[i].to);
}
int add_T(int l,int r,int o,int L,int R){
int ans=0;
if(L<=l&&r<=R){
tag[o]=1;
ans=r-l+1-d[o];
d[o]+=ans;
return ans;
}
int mid=(l+r)>>1,le=o<<1,rr=o<<1|1;
if(tag[o]==1){
d[le]=mid-l+1;
d[rr]=r-mid;
tag[le]=tag[rr]=1;
tag[o]=0;
}else
if(tag[o]==-1){
d[le]=d[rr]=0;
tag[le]=tag[rr]=-1;
tag[o]=0;
}
if(L<=mid)ans=add_T(l,mid,le,L,R);
if(mid<R)ans+=add_T(mid+1,r,rr,L,R);
d[o]=d[le]+d[rr];
return ans;
}
int del_T(int l,int r,int o,int L,int R){
int ans=0;
if(L<=l&&r<=R){
tag[o]=-1;
ans=d[o];
d[o]=0;
return ans;
}
int mid=(l+r)>>1,le=o<<1,rr=o<<1|1;
if(tag[o]==1){
d[le]=mid-l+1;
d[rr]=r-mid;
tag[le]=tag[rr]=1;
tag[o]=0;
}else
if(tag[o]==-1){
d[le]=d[rr]=0;
tag[le]=tag[rr]=-1;
tag[o]=0;
}
if(L<=mid)ans=del_T(l,mid,le,L,R);
if(mid<R)ans+=del_T(mid+1,r,rr,L,R);
d[o]=d[le]+d[rr];
return ans;
}
int download(int p){
int ans=0;
while(top[p]){
ans+=add_T(1,n,1,dfn[top[p]],dfn[p]);
p=fa[top[p]];
}
return ans+add_T(1,n,1,1,dfn[p]);
}
int main(){
n=readint();
fa[0]=cnt=idx=0;
mem(head);
mem(son);
mem(dep);
mem(top);
mem(d);
mem(tag);
dep[top[0]=0]=1;
for(int i=1;i<n;++i){
fa[i]=readint();
e[++cnt]=(edge){i,head[fa[i]]};
head[fa[i]]=cnt;
e[++cnt]=(edge){fa[i],head[i]};
head[i]=cnt;
}
dfs(0);
dfs2(0);
for(int opt=readint();opt--;){
char c=getchar();
for(;!isalpha(c);c=getchar());
if(c=='i')
printf("%d\n",download(readint()));else{
int p=readint();
printf("%d\n",del_T(1,n,1,dfn[p],dfn[p]+sz[p]-1));
}
}
return 0;
}

浙公网安备 33010602011771号