【JZOJ5730】【luoguP2146】【Comet OJC0396】軟件包管理器

description

Linux用戶和OSX用戶必定對軟件包管理器不會陌生。經過軟件包管理器,你能夠經過一行命令安裝某一個軟件包,而後軟件包管理器會幫助你從軟件源下載軟件包,同時自動解決全部的依賴(即下載安裝這個軟件包的安裝所依賴的其它軟件包),完成全部的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是優秀的軟件包管理器。spa

你決定設計你本身的軟件包管理器。不可避免地,你要解決軟件包之間的依賴問題。若是軟件包A依賴軟件包B,那麼安裝軟件包A之前,必須先安裝軟件包B。同時,若是想要卸載軟件包B,則必須卸載軟件包A。如今你已經得到了全部的軟件包之間的依賴關係。並且,因爲你以前的工做,除0號軟件包之外,在你的管理器當中的軟件包都會依賴一個且僅一個軟件包,而0號軟件包不依賴任何一個軟件包。依賴關係不存在環(如有m(m≥2)個軟件包A1,A2,A3,⋯,Am,其中A1依賴A2,A2依賴A3,A3依賴A4,……,A[m-1]依賴Am,而Am依賴A1,則稱這m個軟件包的依賴關係構成環),固然也不會有一個軟件包依賴本身。設計

如今你要爲你的軟件包管理器寫一個依賴解決程序。根據反饋,用戶但願在安裝和卸載某個軟件包時,快速地知道這個操做實際上會改變多少個軟件包的安裝狀態(即安裝操做會安裝多少個未安裝的軟件包,或卸載操做會卸載多少個已安裝的軟件包),你的任務就是實現這個部分。注意,安裝一個已安裝的軟件包,或卸載一個未安裝的軟件包,都不會改變任何軟件包的安裝狀態,即在此狀況下,改變安裝狀態的軟件包數爲0。code


analysis

  • 然而能夠直接樹剖homebrew

  • 對於安裝軟件,就把根到它的路徑所有設爲\(1\)ip

  • 從該點一直跳到根,邊跳邊線段樹區間修改get

  • 對於卸載軟件,就把它和它的子樹所有設爲\(0\)string

  • 這個一次線段樹區間修改就能夠了io

  • 操做先後不一樣的的數個數,能夠拿操做先後的整棵樹裏的\(1\)的數目相減獲得ast


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#define MAXN 100005
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])

using namespace std;

ll last[MAXN],next[MAXN],tov[MAXN];
ll fa[MAXN],top[MAXN],size[MAXN],depth[MAXN],heavy_son[MAXN];
ll tr[MAXN<<2],bz[MAXN<<2],to_tree[MAXN],to_num[MAXN];
ll n,q,tot;
char s[10];

inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline ll abs(ll x){return x>0?x:-x;}
inline void link(ll x,ll y){next[++tot]=last[x],last[x]=tot,tov[tot]=y;}
inline void dfs1(ll x)
{
    rep(i,x)
    {
        depth[tov[i]]=depth[x]+1,size[tov[i]]=1,dfs1(tov[i]),size[x]+=size[tov[i]];
        if (size[tov[i]]>size[heavy_son[x]])heavy_son[x]=tov[i];
    }
}
inline void dfs2(ll x,ll y)
{
    if (!x)return;top[x]=y;
    to_tree[x]=++tot,to_num[tot]=x,dfs2(heavy_son[x],y);
    rep(i,x)if (tov[i]!=heavy_son[x])dfs2(tov[i],tov[i]);
}
inline void maketree(ll t,ll l,ll r)
{
    bz[t]=-1;if (l==r)return;
    ll mid=(l+r)>>1;maketree(t<<1,l,mid),maketree((t<<1)+1,mid+1,r);
}
inline void downdata(ll t,ll l,ll r)
{
    if (bz[t]==-1)return;ll mid=(l+r)>>1;
    tr[t<<1]=(mid-l+1)*bz[t],tr[(t<<1)+1]=(r-mid)*bz[t];
    bz[t<<1]=bz[(t<<1)+1]=bz[t],bz[t]=-1;
}
inline void tree_modify(ll t,ll l,ll r,ll x,ll y,ll z)
{
    if (l==x && y==r){tr[t]=(r-l+1)*z,bz[t]=z;return;}
    ll mid=(l+r)>>1;downdata(t,l,r);
    if (y<=mid)tree_modify(t<<1,l,mid,x,y,z);
    else if (x>mid)tree_modify((t<<1)+1,mid+1,r,x,y,z);
    else tree_modify(t<<1,l,mid,x,mid,z),tree_modify((t<<1)+1,mid+1,r,mid+1,y,z);
    tr[t]=tr[t<<1]+tr[(t<<1)+1];
}
inline void modify(ll x)
{
    while (top[x]!=1)tree_modify(1,1,n,to_tree[top[x]],to_tree[x],1),x=fa[top[x]];
    tree_modify(1,1,n,1,to_tree[x],1);
}
int main()
{
    //freopen("P2146.in","r",stdin);
    freopen("manager.in","r",stdin);
    freopen("manager.out","w",stdout);
    n=read();fo(i,2,n)link(fa[i]=read()+1,i);
    tot=0,dfs1(depth[1]=size[1]=1),
    dfs2(1,1),maketree(1,1,n),q=read();
    while (q--)
    {
        scanf("%s",&s);ll x=read()+1,tmp=tr[1];
        if (s[0]=='i')
        {
            modify(x),printf("%lld\n",abs(tr[1]-tmp));
            continue;
        }
        tree_modify(1,1,n,to_tree[x],to_tree[x]+size[x]-1,0);
        printf("%lld\n",abs(tr[1]-tmp));
    }
    return 0;
}
相關文章
相關標籤/搜索