• 【BZOJ4196】【Noi2015】软件包管理器


    原题传送门

    题意:

    给你一棵树,有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
    ",install(x));
            else printf("%d
    ",uninstall(x));
        }
    }
    int main(){init();solve();return 0;}
  • 相关阅读:
    让Vim查找字符忽略大小写
    How to Add a User to Sudoers on Ubuntu
    Docker 批量删除images
    解决 Laradock 安装时候出现 Can't open /home/laradock/.nvm/nvm.sh 的问题
    Add User To Docker Group In Ubuntu Linux
    Parted分区和创建逻辑卷LVM
    How To List Users and Groups on Linux
    How to Install Node.js and NPM on Mac OS
    linux中的alias命令详解
    Hadoop数据类型
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ4196.html
Copyright © 2020-2023  润新知