题解:P2146 [NOI2015] 软件包管理器
解题思路
对于两种操作,
install : 求从根节点到当前节点这段路径中没有被安装过的软件数量。
unstall : 求当前子树没有被安装过的软件数量。
很显然,对于这两种操作,树链剖分算法是很不错的选择。
AC 代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define maxn 100005
#define ls (p<<1)
#define rs (p<<1|1)
int n,q,a[maxn];
int fa[maxn],dfn[maxn],top[maxn];
int son[maxn],siz[maxn],deep[maxn];
int dfs_cnt;
struct edge
{
int v,next;
}e[maxn<<1|1];
int head[maxn],k;
inline void add(int u,int v)
{
e[k]=(edge){v,head[u]};
head[u]=k++;
}
void dfs1(int u)
{
deep[u]=deep[fa[u]]+1;
son[u]=-1;
siz[u]=1;
for(int i=head[u];~i;i=e[i].next)
{
dfs1(e[i].v);
siz[u]+=siz[e[i].v];
if(son[u]==-1||siz[son[u]]<siz[e[i].v]) son[u]=e[i].v;
}
}
void dfs2(int u,int t)
{
top[u]=t;
dfn[u]=++dfs_cnt;
if(son[u]==-1) return;
dfs2(son[u],t);
for(int i=head[u];~i;i=e[i].next)
if(e[i].v!=son[u])
dfs2(e[i].v,e[i].v);
}
struct node
{
int l,r,tag,lazy;
}tree[maxn<<2|1];
void build(int p,int l,int r)
{
tree[p].l=l;tree[p].r=r;
if(l==r)
{
tree[p].tag= (l==1)?1:0;
tree[p].lazy=-1;
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
if(tree[ls].tag!=tree[rs].tag||tree[ls].tag==-1) tree[p].tag=-1;
else tree[p].tag=tree[ls].tag;
}
inline void push_down(int p)
{
if(tree[p].lazy==-1) return;
tree[ls].tag=tree[ls].lazy=tree[rs].tag=tree[rs].lazy=tree[p].lazy;
tree[p].lazy=-1;
}
void change(int p,int l,int r,int d)
{
if(l<=tree[p].l&&r>=tree[p].r)
{
tree[p].tag=d;
tree[p].lazy=d;
return;
}
push_down(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid) change(ls,l,r,d);
if(r>mid) change(rs,l,r,d);
if(tree[ls].tag!=tree[rs].tag||tree[ls].tag==-1) tree[p].tag=-1;
else tree[p].tag=tree[ls].tag;
}
int query(int p,int l,int r,int aim)
{
if(tree[p].tag!=-1&&l<=tree[p].l&&r>=tree[p].r)
return tree[p].tag==aim?(tree[p].r-tree[p].l+1):0;
push_down(p);
int mid=(tree[p].l+tree[p].r)>>1,ans=0;
if(l<=mid) ans+=query(ls,l,r,aim);
if(r>mid) ans+=query(rs,l,r,aim);
return ans;
}
inline int querypath(int x)
{
int ans=0;
while(top[x]!=1)
{
ans+=query(1,dfn[top[x]],dfn[x],0);
change(1,dfn[top[x]],dfn[x],1);
x=fa[top[x]];
}
ans+=query(1,dfn[top[x]],dfn[x],0);
change(1,dfn[top[x]],dfn[x],1);
return ans;
}
inline int querytree(int x)
{
int ans=query(1,dfn[x],dfn[x]+siz[x]-1,1);
change(1,dfn[x],dfn[x]+siz[x]-1,0);
return ans;
}
int main()
{
scanf("%d",&n);
memset(head,-1,sizeof(head));
a[1]=1;
for(int i=2;i<=n;i++)
{
scanf("%d",&fa[i]);
fa[i]++;
add(fa[i],i);
}
dfs1(1);
dfs2(1,1);
build(1,1,n);
scanf("%d",&q);
char opt[20];int x;
while(q--)
{
scanf("\n%s%d",opt,&x);
x++;
if(opt[0]=='i') printf("%d\n",querypath(x));
else printf("%d\n",querytree(x));
}
return 0;
}

浙公网安备 33010602011771号