P2146 [NOI2015] 软件包管理器 ——树链剖分 线段树

题意

分析

我们认为一个点安装/不安装对应 1/0。

对于安装操作,查询目标点到根节点路径上的安装数并将路径上的点全部修改为 1 。

对于卸载操作,查询目标点子树内的 1 的个数并将子树的点全部修改为 0 。


codes:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;

inline int read()
{
    register char c=getchar();int x=0;
    while(!isdigit(c))c=getchar();
    while(isdigit(c)){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return x;
}

int n,q,dep[N],f[N],siz[N],son[N];
int deg[N],top[N],id[N],rk[N],dfn,sta[N];
vector<int>to[N];

void go1(int u,int fa)
{
    f[u]=fa;dep[u]=dep[fa]+1;siz[u]=1;
    for(int i=0;i<deg[u];++i)
    {
        int v=to[u][i];
        go1(v,u);
        if(siz[v]>siz[son[u]])son[u]=v;
        siz[u]+=siz[v];
    }

}
void go2(int u,int tp)
{
    id[u]=++dfn;rk[dfn]=u;top[u]=tp;
    if(son[u])go2(son[u],tp);
    for(int i=0;i<deg[u];++i)
    {
        int v=to[u][i];
        if(v==son[u])continue;
        go2(v,v);
    }
}

struct segtree
{

    struct node
    {
        int val,tag;
        node(){tag=-1;}
    }s[N<<2];
    void pushup(int i){s[i].val=s[i<<1].val+s[i<<1|1].val;}

    void pushtag(int i,int z,int x){s[i].val=x*z;s[i].tag=z;}

    void pushdown(int i,int l,int r)
    {
        if(s[i].tag==-1)return ;
        int mid=(l+r)>>1;
        pushtag(i<<1,s[i].tag,mid-l+1);
        pushtag(i<<1|1,s[i].tag,r-mid);
        s[i].tag=-1;
    }

    int que(int i,int l,int r,int x,int y)
    {
        if(l>=x && r<=y)return s[i].val;
        int mid=(l+r)>>1,sum=0;pushdown(i,l,r);
        if(x<=mid)sum+=que(i<<1,l,mid,x,y);
        if(y>mid)sum+=que(i<<1|1,mid+1,r,x,y);
        return sum;
    }

    void fix(int i,int l,int r,int x,int y,int z)
    {
        if(l>=x && r<=y){pushtag(i,z,r-l+1);return ;}
        int mid=(l+r)>>1;pushdown(i,l,r);
        if(x<=mid)fix(i<<1,l,mid,x,y,z);
        if(y>mid)fix(i<<1|1,mid+1,r,x,y,z);
        pushup(i);
    }

    int got(int x,int y){return que(1,1,n,x,y);}
    void cl(int x,int y,int z){fix(1,1,n,x,y,z);}
}T;

void init()
{
    scanf("%d",&n);
    for(int i=2,x;i<=n;++i)
    {
        x=read()+1;
        ++deg[x];
        to[x].push_back(i);
    }
    go1(1,0);
    go2(1,1);
}

int rer(int x)
{
    int sum=0;
    while(top[x]!=1)
    {
        int num=dep[x]-dep[top[x]]+1-T.got(id[top[x]],id[x]);
        if(num==0)return sum;
        sum+=num;
        T.cl(id[top[x]],id[x],1);
        x=f[top[x]];
    }
    sum+=dep[x]-dep[1]+1-T.got(id[1],id[x]);
    T.cl(id[1],id[x],1);
    return sum;
}

void work()
{
    scanf("%d",&q);
    while(q--)
    {
        char t=getchar();
        while(t>'z' || t<'a')t=getchar();
        int x=read()+1;
        if(t=='i')
        {
            if(T.got(id[x],id[x])==1){printf("0\n");continue;}
            printf("%d\n",rer(x));
        }
        else
        {
            if(T.got(id[x],id[x])==0){printf("0\n");continue;}
            printf("%d\n",T.got(id[x],id[x]+siz[x]-1));
            T.cl(id[x],id[x]+siz[x]-1,0);
        }
    }
}

int main()
{
    init();
    work();
    return 0;
}
posted @ 2025-02-23 21:48  Glowingfire  阅读(13)  评论(0)    收藏  举报