BZOJ4196Noi2015软件包管理器
Posted Melacau----论一个蒟蒻的自我修养
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4196Noi2015软件包管理器相关的知识,希望对你有一定的参考价值。
题意:
给你一棵树,有2种操作:
1.使得某个点到根节点路径上的所有点权值赋为1。
2.使得某节点的子树中所有节点权值赋为0.
每次操作要求输出权值更改的节点个数。
解题思路:
显然是用树剖来解决问题,考虑用区间赋值的线段树维护区间内1的个数,然后直接按题意树剖求解即可。
操作1的时间效率为\( O ( \log^{2} n) \) ,操作2的时间效率为\( O( \log n) \) ,总时间复杂度最坏为\( O (m \log^{2} n) \).
BZOJ上跑了5900ms,6960KB
#include <stdio.h> #define MN 100005 #define Mn (1<<17) #define ls (k<<1) #define rs (k<<1|1) #define mid (l+r>>1) #define v edge[i].to int mark[Mn<<1],sum[Mn<<1],siz[MN],dep[MN],son[MN],fa[MN],top[MN],head[MN],cnt,n,q,dfsn,l[MN],r[MN]; struct zxy{int to,nxt;}edge[MN]; inline void ins(int x,int y){edge[++cnt].to=y,edge[cnt].nxt=head[x],head[x]=cnt;} inline int in(){ int x=0,f=1;char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*f; } inline void dfs1(int u,int d){ dep[u]=d,siz[u]=1,son[u]=-1; for (register int i=head[u]; i; i=edge[i].nxt){ dfs1(v,d+1);siz[u]+=siz[v]; if (son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } inline void dfs2(int u,int tp){ top[u]=tp;l[u]=(++dfsn);if (son[u]!=-1) dfs2(son[u],tp); for (register int i=head[u]; i; i=edge[i].nxt) if (v!=son[u]) dfs2(v,v);r[u]=dfsn; } inline void pushdown(int k,int l,int r){ if (mark[k]==-1)return; register int x=r-l+1;mark[ls]=mark[rs]=mark[k]; sum[ls]=mark[k]*(x-(x>>1));sum[rs]=mark[k]*(x>>1);mark[k]=-1; } inline void A(int l,int r,int a,int b,int k,int ad){ if (a<=l&&r<=b) {mark[k]=ad; sum[k]=(r-l+1)*ad;return;} pushdown(k,l,r);if (a<=mid) A(l,mid,a,b,ls,ad); if (b>mid) A(mid+1,r,a,b,rs,ad);sum[k]=sum[ls]+sum[rs]; } inline int Q(int l,int r,int a,int b,int k){ if (a==l&&b==r) return sum[k];pushdown(k,l,r); if (b<=mid) return Q(l,mid,a,b,ls); if (mid<a) return Q(mid+1,r,a,b,rs); return Q(l,mid,a,mid,ls)+Q (mid+1,r,mid+1,b,rs); } inline int install(int x){ register int res=0; while (top[x]) res+=l[x]-l[top[x]]-Q(1,n,l[top[x]],l[x],1)+1,A(1,n,l[top[x]],l[x],1,1),x=fa[top[x]]; res+=l[x]-l[0]+1-Q(1,n,l[0],l[x],1);A(1,n,l[0],l[x],1,1);return res; } inline int uninstall(int x){ register int res=Q(1,n,l[x],r[x],1); A(1,n,l[x],r[x],1,0);return res; } void init(){ n=in();for (register int i=1; i<n; ++i) fa[i]=in(),ins(fa[i],i); dfs1(0,1);dfs2(0,0); } void solve(){ for (q=in(); q--;){ register char op[20];scanf("%s",op);register int x=in(); if (op[0]==‘i‘) printf("%d\n",install(x)); else printf("%d\n",uninstall(x)); } } int main(){init();solve();return 0;}
以上是关于BZOJ4196Noi2015软件包管理器的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4196 [Noi2015]软件包管理器——树链剖分
Bzoj 4196: [Noi2015]软件包管理器 树链剖分
[UOJ#128][BZOJ4196][Noi2015]软件包管理器