【題解】Luogu P2146 [NOI2015]軟件包管理器

題面:https://www.luogu.org/problemnew/lists?name=2146html

這道題要用樹鏈剖分,我博客裏有對樹鏈剖分的詳細介紹

這道題就是樹鏈剖分的模板,詳細解釋見程序。ios

學完樹的dfs序,lca,線段樹食用更佳。c++

不會這些學什麼樹剖(逃~spa

#include <bits/stdc++.h> //萬能頭文件
using namespace std;
int n,q,tot;
int fa[100005],size[100005],dep[100005],son[100005];
int lo[100005],top[100005];
int sum[800005],tag[800005];    
vector <int> allson[100005];
//線段樹
void pushup(int x)//更新
{
    sum[x]=sum[x<<1]+sum[(x<<1)+1];
}
void pushdown(int x,int l,int r)//清除懶標記
{
    if(tag[x]!=-1)
    {
        int m=(l+r)>>1;
        int ls=x<<1;
        int rs=ls+1;
        tag[ls]=tag[rs]=tag[x];
        sum[ls]=(m-l+1)*tag[x];
        sum[rs]=(r-m)*tag[x];
        tag[x]=-1; 
    }
}
void update(int x,int l,int r,int L,int R,int v)//修改
{
    if(R<l||r<L)
        return;
    if(L<=l&&r<=R)
    {
        sum[x]=(r-l+1)*v;
        tag[x]=v;
        return;
    }
    pushdown(x,l,r);
    int m=(l+r)>>1;
    update(x<<1,l,m,L,R,v);
    update((x<<1)+1,m+1,r,L,R,v);
    pushup(x);
}
//樹鏈剖分
void change(int x,int y,int v)//相似lca
{
    int fx=top[x],fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx]<dep[fy])
            swap(x,y),swap(fx,fy);
        update(1,1,tot,lo[fx],lo[x],v);
        x=fa[fx],fx=top[x];
    }
    if(lo[x]>lo[y])
        swap(x,y);
    update(1,1,tot,lo[x],lo[y],v);
}
void dfs1(int x)
{
    size[x]=1;
    for(int i=0;i<allson[x].size();++i)
    {
        int v=allson[x][i];
        dep[v]=dep[x]+1;//深度
        dfs1(v);
        size[x]+=size[v];//子樹大小
        if(size[v]>size[son[x]])
            son[x]=v;//重兒子
    }
}
void dfs2(int x,int t)
{
    lo[x]=++tot;    
    top[x]=t;//重鏈父親
    if(son[x])
        dfs2(son[x],t);
    for(int i=0;i<allson[x].size();++i)
    {
        int v=allson[x][i];
        if(v!=son[x])
            dfs2(v,v);
    }
} 
int main()
{
    memset(tag,-1,sizeof(tag)); //lazy_tag爲-1表示沒有
    ios::sync_with_stdio(0);
    cin>>n;
    fa[1]=1;
    for(int i=2;i<=n;++i)
    {
        int x;
        cin>>x;
        fa[i]=x+1;
        allson[x+1].push_back(i);
    }
    //預處理
    dfs1(1);
    dfs2(1,1);
    cin>>q;
    while(q--)
    {
        string s;
        int x;
        cin>>s>>x;
        x++;
        int before=sum[1];//改以前
        if(s=="install")
        {
            change(1,x,1);//1到x路上全改爲1
            int after=sum[1];//改後
            cout<<fabs(before-after)<<endl;
        }
        else
        {
            update(1,1,n,lo[x],lo[x]+size[x]-1,0);//把x的子樹改爲0
            int after=sum[1];//改後
            cout<<fabs(before-after)<<endl;
        }
    }
    return 0;
}
相關文章
相關標籤/搜索