[NOI2015] 软件包管理器

题目链接:戳我
树链剖分维护。
1表示安装的状态,0表示没有安装的状态。
如果install就是把当前点到根的所有点都变成1,然后计算前后的\(\delta\)
如果uninstall呢,就是把自己的子树变成0,答案也是前后的\(\delta\)
具体可以参照代码(不过我的代码常数好大啊,跑得好慢。。。。)
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 400010
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
    return x*f;
}
int n,m,t,tot;
int head[MAXN],sum[MAXN],tag[MAXN],siz[MAXN],top[MAXN],dep[MAXN],son[MAXN],id[MAXN],fa[MAXN];
char cur[20];
struct Edge{int nxt,to,dis;}edge[MAXN<<1];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline void add(int from,int to,int dis)
{   
    edge[++t].to=to,edge[t].nxt=head[from],edge[t].dis=dis;
    head[from]=t;
}
inline void push_up(int x){sum[x]=sum[ls(x)]+sum[rs(x)];}
inline void push_down(int x,int l,int r)
{
    if(tag[x]==0) return;
    if(tag[x]==1)
    {
        tag[ls(x)]=tag[rs(x)]=1;
        sum[ls(x)]=(r-l+1)-(r-l+1)/2;
        sum[rs(x)]=(r-l+1)/2;
    }
    else
    {
        tag[ls(x)]=tag[rs(x)]=-1;
        sum[ls(x)]=sum[rs(x)]=0;
    }
    tag[x]=0;
}
inline void update(int x,int l,int r,int ll,int rr,int k)
{
    if(ll<=l&&r<=rr)
    {
        sum[x]=(r-l+1)*k;
        tag[x]=(k==1?1:2);
        return;
    }
    int mid=(l+r)>>1;
    push_down(x,l,r);
    if(ll<=mid) update(ls(x),l,mid,ll,rr,k);
    if(mid<rr) update(rs(x),mid+1,r,ll,rr,k);
    push_up(x);
}
inline int query(int x,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr) return sum[x];
    int mid=(l+r)>>1;
    push_down(x,l,r);
    int cur_ans=0;
    if(ll<=mid) cur_ans+=query(ls(x),l,mid,ll,rr);
    if(mid<rr) cur_ans+=query(rs(x),mid+1,r,ll,rr);
    return cur_ans;
}
inline void dfs1(int x,int pre)
{
    int maxx=-1;
    dep[x]=dep[pre]+1;
    fa[x]=pre;
    siz[x]=1;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v!=pre)
        {
            dfs1(v,x);
            siz[x]+=siz[v];
            if(siz[v]>maxx) maxx=siz[v],son[x]=v;
        }
    }
}
inline void dfs2(int x,int topf)
{
    id[x]=++tot;
    top[x]=topf;
    if(son[x]) dfs2(son[x],topf);
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v!=fa[x]&&v!=son[x]) dfs2(v,v);
    }
}
inline int modify(int x,int y,int k)
{
    int cur_ans=0;
    while(top[x]!=top[y])
    {
        if(dep[x]<dep[y]) swap(x,y);
        cur_ans-=query(1,1,n,id[top[x]],id[x]);
        update(1,1,n,id[top[x]],id[x],k);
        cur_ans+=query(1,1,n,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    cur_ans-=query(1,1,n,id[y],id[x]);
    update(1,1,n,id[y],id[x],k);
    cur_ans+=query(1,1,n,id[y],id[x]);
    return cur_ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    n=read();
    for(int i=1;i<n;i++)
    {
        int cur=read()+1;
        add(cur,i+1,0),add(i+1,cur,0);
    }
    m=read();
    dfs1(1,0);
    dfs2(1,1);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",cur);
        int x=read()+1;
        if(cur[0]=='i') 
            printf("%d\n",modify(1,x,1));
        else 
        {
            printf("%d\n",query(1,1,n,id[x],id[x]+siz[x]-1));
            update(1,1,n,id[x],id[x]+siz[x]-1,0);
        }
    }
    return 0;
}
posted @ 2019-01-19 17:36  风浔凌  阅读(157)  评论(0编辑  收藏  举报