bzoj4196 [Noi2015]软件包管理器——树链剖分

Posted zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4196 [Noi2015]软件包管理器——树链剖分相关的知识,希望对你有一定的参考价值。

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4196

树链剖分。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=1e5+5;
int n,m,fa[maxn],dfn[maxn],end[maxn],top[maxn],to[maxn],siz[maxn],head[maxn],ct,tim;
struct N{
    int to,next;
    N(int t=0,int n=0):to(t),next(n) {}
}edge[maxn];
struct T{int sum,siz; bool f[3];}t[maxn<<2];
int rd()
{
    int ret=0;char ch=getchar();
    while(ch<0||ch>9)ch=getchar();
    while(ch>=0&&ch<=9)ret=ret*10+ch-0,ch=getchar();
    return ret;
}
void dfs(int x)
{
    siz[x]=1;
    for(int i=head[x],u;i;i=edge[i].next)
    {
        dfs(u=edge[i].to);
        if(siz[u]>siz[to[x]])to[x]=u;
        siz[x]+=siz[u];
    }
}
void dfs2(int x)
{
    dfn[x]=++tim;//不在dfs 
    if(to[x])top[to[x]]=top[x],dfs2(to[x]);
    for(int i=head[x],u;i;i=edge[i].next)
    {
        if((u=edge[i].to)==to[x])continue;
        top[u]=u; dfs2(u);
    }
    end[x]=tim;
}
void pushup(int x)
{
    int ls=(x<<1),rs=(x<<1|1);
    t[x].siz=t[ls].siz+t[rs].siz;
    t[x].sum=t[ls].sum+t[rs].sum;
}
void pushdown(int x)
{
    if(!t[x].f[0]&&!t[x].f[1])return;
    int ls=(x<<1),rs=(x<<1|1);
    for(int i=0;i<=1;i++)
        if(t[x].f[i])
        {
            t[x].f[i]=0; t[ls].f[i]=1; t[rs].f[i]=1;
            t[ls].f[!i]=0; t[rs].f[!i]=0;
            t[ls].sum=t[ls].siz*i; t[rs].sum=t[rs].siz*i;
        }
}
void build(int x,int l,int r)
{
    if(l==r){t[x].siz=1;return;}
    int mid=((l+r)>>1);
    build(x<<1,l,mid); build(x<<1|1,mid+1,r);
    pushup(x);
}
int query(int x,int l,int r,int L,int R,int val)
{
    if(l>=L&&r<=R)
    {
        if(val)return t[x].sum;
        else return t[x].siz-t[x].sum;
    }
    int mid=((l+r)>>1),ret=0;
    pushdown(x);
    if(mid>=L)ret+=query(x<<1,l,mid,L,R,val);
    if(mid<R)ret+=query(x<<1|1,mid+1,r,L,R,val);
    return ret;
}
void update(int x,int l,int r,int L,int R,int val)
{
    if(l>=L&&r<=R)
    {
        t[x].f[val]=1;  t[x].f[!val]=0;
        t[x].sum=t[x].siz*val; return;
    }
    int mid=((l+r)>>1);
    if(mid>=L)update(x<<1,l,mid,L,R,val);
    if(mid<R)update(x<<1|1,mid+1,r,L,R,val);
    pushup(x);
}
int ask(int x)
{
    int ret=0;
    while(x)
    {
        int l=dfn[top[x]],r=dfn[x];
        ret+=query(1,1,n,l,r,0);
        update(1,1,n,l,r,1);
        x=fa[top[x]];
    }
    return ret;
}
int main()
{
    n=rd();
    for(int i=2;i<=n;i++)
    {
        fa[i]=rd()+1;
        edge[++ct]=N(i,head[fa[i]]);head[fa[i]]=ct;
    }
    dfs(1); top[1]=1; dfs2(1); build(1,1,n);
    m=rd(); char ch[15];
    for(int i=1,x;i<=m;i++)
    {
        scanf("%s",&ch); x=rd()+1;
        if(ch[0]==u)
        {
            printf("%d
",query(1,1,n,dfn[x],end[x],1));
            update(1,1,n,dfn[x],end[x],0);
        }
        if(ch[0]==i)
        {
            printf("%d
",ask(x));
        }
    }
    return 0;
}

 

以上是关于bzoj4196 [Noi2015]软件包管理器——树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj 4196: [Noi2015]软件包管理器 树链剖分

bzoj4196: [Noi2015]软件包管理器

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

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

bzoj4196[Noi2015]软件包管理器

BZOJ_4196_[Noi2015]软件包管理器_树链剖分