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]软件包管理器 树链剖分

bzoj4196: [Noi2015]软件包管理器

[UOJ#128][BZOJ4196][Noi2015]软件包管理器

bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

bzoj4196[Noi2015]软件包管理器