BZOJ 4196 软件包管理器(树链剖分子树)

来源:互联网 发布:java的发展趋势 编辑:程序博客网 时间:2024/06/05 18:32

树链剖分同时记录子树区间

对于install操作,直接爬上根结点,进行更新查询操作

对于unstall操作,直接询问子树区间,更新子树区间


#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 300005int fir[maxn],nex[maxn],v[maxn],e_max;int son[maxn],fa[maxn],top[maxn],siz[maxn],deep[maxn],tot;int in[maxn],out[maxn];int sum[2*maxn],tag[2*maxn];void init_(){    memset(fir,-1,sizeof fir);    memset(son,-1,sizeof son);    memset(in,0,sizeof in);    memset(out,0,sizeof out);    e_max=0;    tot=1;}void add_edge(int s,int t){    int e=e_max++;    v[e]=t;    nex[e]=fir[s];    fir[s]=e;}void dfs1(int k,int pre,int d){    deep[k]=d;    siz[k]=1;    fa[k]=pre;    for(int i=fir[k];~i;i=nex[i])    {        int e=v[i];        if(e!=pre)        {            dfs1(e,k,d+1);            siz[k]+=siz[e];            if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e;        }    }}void dfs2(int k,int sp){    top[k]=sp;    in[k]=tot++;    out[k]=in[k];    if(son[k]==-1) return ;    dfs2(son[k],sp);    out[k]=max(out[k],out[son[k]]);    for(int i=fir[k];~i;i=nex[i])    {        int e=v[i];        if(e!=son[k]&&e!=fa[k])        {            dfs2(e,e);            out[k]=max(out[k],out[e]);        }    }}void init(int l,int r,int k){    tag[k]=-1;    if(l==r)    {        sum[k]=1;        return ;    }    int mid=l+r>>1;    init(l,mid,k<<1);    init(mid+1,r,k<<1|1);    sum[k]=sum[k<<1]+sum[k<<1|1];}void pushdown(int l,int r,int k){    if(tag[k]==-1) return ;    int mid=l+r>>1;    tag[k<<1]=tag[k<<1|1]=tag[k];    if(tag[k]) sum[k<<1]=mid-l+1,sum[k<<1|1]=r-mid;    else sum[k<<1]=sum[k<<1|1]=0;    tag[k]=-1;}void update(int d,int s,int t,int l,int r,int k){    if(s==l&&r==t)    {        tag[k]=d;        if(d) sum[k]=r-l+1;        else sum[k]=0;        return ;    }    pushdown(l,r,k);    int mid=l+r>>1;    if(t<=mid) update(d,s,t,l,mid,k<<1);    else if(s>mid) update(d,s,t,mid+1,r,k<<1|1);    else    {        update(d,s,mid,l,mid,k<<1);        update(d,mid+1,t,mid+1,r,k<<1|1);    }    sum[k]=sum[k<<1]+sum[k<<1|1];}int query(int s,int t,int l,int r,int k){    if(s==l&&r==t)    {        return sum[k];    }    pushdown(l,r,k);    int mid=l+r>>1;    if(t<=mid) return query(s,t,l,mid,k<<1);    else if(s>mid) return query(s,t,mid+1,r,k<<1|1);    else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1);}int Query(int s,int t){    int ans=0;    int f1=top[s],f2=top[t];    while(f1!=f2)    {        if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t);        ans+=query(in[f1],in[s],1,tot-1,1);        update(0,in[f1],in[s],1,tot-1,1);        s=fa[f1];        f1=top[s];    }    if(deep[s]>deep[t]) swap(s,t);    ans+=query(in[s],in[t],1,tot-1,1);    update(0,in[s],in[t],1,tot-1,1);    return ans;}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        init_();        for(int i=1;i<n;i++)        {            int a;            scanf("%d",&a);            add_edge(a,i);            add_edge(i,a);        }        dfs1(0,-1,1);        dfs2(0,0);        init(1,tot-1,1);        int m;        scanf("%d",&m);        while(m--)        {            char s[20];            int x;            scanf("%s%d",s,&x);            if(!strcmp(s,"install"))            {                if(!query(in[x],in[x],1,tot-1,1))                {                    printf("0\n");                    continue;                }                int ans=Query(x,0);                printf("%d\n",ans);            }            else            {                if(query(in[x],in[x],1,tot-1,1))                {                    printf("0\n");                    continue;                }                printf("%d\n",siz[x]-query(in[x],out[x],1,tot-1,1));                update(1,in[x],out[x],1,tot-1,1);            }        }    }    return 0;}


0 0
原创粉丝点击