码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-04-26 11:48:10      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:reg   div   blank   www   传送门   getchar   define   题意   节点   

原题传送门

题意:

给你一棵树,有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;}

 

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

标签:reg   div   blank   www   传送门   getchar   define   题意   节点   

原文地址:http://www.cnblogs.com/Melacau/p/BZOJ4196.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!