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

【Luogu P2146】软件包管理器

时间:2019-11-06 10:25:37      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:区间   tmp   覆盖   关系   void   def   ring   cin   ret   

Luogu P2146
由于对于每一个软件包有且只有一个依赖的软件包,且依赖关系不存在环。
很显然这是一个树形的结构。
再看题目要求的操作,安装实际上对应的是覆盖根节点到当前节点的路径,卸载则是覆盖该节点的整颗子树。
对于这样的操作,树链剖分+线段树可以很轻松地维护。
值得注意的是,根节点编号为0,我为了方便操作,把所有节点的编号都加了1
线段树的懒标记在没有使用的情况下应该标记为-1,因为0代表的是整个区间被覆盖为0。不能判断为标记为0就不进行push_down,因为卸载之后其子树上的所有节点都应该被标记为0。而对于完全没有使用过的标记,如果置为0,则会影响到子树上被安装的节点。
代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson root<<1
#define rson root<<1|1
#define mid ((l+r)>>1)
using namespace std;
struct data
{
    int to,next;
}edge[200005];
int cnt,head[100005],tag[400005],tree[400005],d[100005],f[100005],id[100005],size[100005];
int wson[100005],top[100005],n,x,y,q;
string st;
inline void add(int x,int y)
{
    edge[++cnt].to=y;
    edge[cnt].next=head[x];
    head[x]=cnt;
}
inline void push_down(int root,int l,int r) 
{
    if (tag[root]==-1) return ;
    tree[lson]=(mid-l+1)*tag[root];
    tree[rson]=(r-mid)*tag[root];
    tag[lson]=tag[rson]=tag[root];
    tag[root]=-1;
}
inline void push_up(int root)
{
    tree[root]=tree[lson]+tree[rson];
}
void segupd(int root,int l,int r,int al,int ar,int flag)
{
    if (ar<l||r<al) return ;
    if (al<=l&&r<=ar)
    {
        tag[root]=flag;
        if (tag[root]) tree[root]=r-l+1;
        else tree[root]=0; 
        return;
    }
    push_down(root,l,r);
    segupd(lson,l,mid,al,ar,flag);
    segupd(rson,mid+1,r,al,ar,flag);
    push_up(root);
}
int query(int root,int l,int r,int al,int ar)
{
    if (ar<l||r<al) return 0;
    if (al<=l&&r<=ar)
        return tree[root];
    int ret=0;
    push_down(root,l,r);
    ret+=query(lson,l,mid,al,ar);
    ret+=query(rson,mid+1,r,al,ar);
    return ret;
}
void dfs1(int now,int fa,int deep)
{
    d[now]=deep;
    f[now]=fa;
    size[now]++;
    for (int i=head[now];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if (v==fa) continue;
        dfs1(v,now,deep+1);
        size[now]+=size[v];
        if (size[v]>size[wson[now]]) wson[now]=v;
    }
}
void dfs2(int now,int t)
{
    top[now]=t;
    id[now]=++cnt;
    if (wson[now]) dfs2(wson[now],t);
    for (int i=head[now];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if (wson[now]==v||v==f[now]) continue;
        dfs2(v,v);
    }
}
int inst(int now)
{
    int tmp=query(1,1,n,id[top[now]],id[now]);
    int ans=0;
    while (!tmp&&now!=0)
    {
        ans+=id[now]-id[top[now]]+1;
        segupd(1,1,n,id[top[now]],id[now],1);
        now=f[top[now]];
        if (now==0) return ans; 
        tmp=query(1,1,n,id[top[now]],id[now]);
    }
    if (now!=0) 
    {
        ans+=id[now]-id[top[now]]+1-tmp;
        segupd(1,1,n,id[top[now]],id[now],1);
    }
    return ans;
}
inline int uninst(int now)
{
    int ans=query(1,1,n,id[now],id[now]+size[now]-1);
    segupd(1,1,n,id[now],id[now]+size[now]-1,0);
    return ans;
}
void build(int root,int l,int r)
{
    if (l==r) 
    {
        tree[root]=0;
        tag[root]=-1;
        return ;
    }
    build(lson,l,mid);
    build(rson,mid+1,r);
    push_up(root);
} 
int main()
{
    scanf("%d",&n);
    for (int i=1;i<n;i++) 
    {
        scanf("%d",&x);
        add(i+1,x+1);
        add(x+1,i+1);
    }
    dfs1(1,0,0);
    cnt=0;
    dfs2(1,1);
    build(1,1,n);
    scanf("%d\n",&q);
    for (int i=1;i<=q;i++)
    {
        cin>>st;
        scanf("%d",&x);
        if (st=="install") 
            printf("%d\n",inst(x+1));
        else 
            printf("%d\n",uninst(x+1));
    }
    return 0;
}

【Luogu P2146】软件包管理器

标签:区间   tmp   覆盖   关系   void   def   ring   cin   ret   

原文地址:https://www.cnblogs.com/notscience/p/11803483.html

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