[NOI2015]软件包管理器(树链刨分)

其实也算是个板子吧,思想还是很好的

一开始真的没什么思路,然后想了想要是这个软件已经装上了就设成1,不然设成0,

查询的话直接做点到根节点的权值和就好了,要是卸载了,就查询这个点为为根节点的权值和,然后用子树大小减去上面的权值和就好了

区间覆盖的话将lazytag改动一下就好了

题面

放上丑丑的代码

#include<bits/stdc++.h>
#define ls(x) x<<1
#define rs(x) x<<1|1
using namespace std;
const int N=4e5+6;
int m,n,k,p,l,cnt,tot,res,root;
int lg[N],sum[N],son[N],fa[N],dep[N],top[N],head[N],size[N],id[N];
struct edge
{
    int nx,to;
} e[N];
void add_edge(int a,int b)
{
    cnt++;e[cnt].to=b;e[cnt].nx=head[a];head[a]=cnt;
    cnt++;e[cnt].to=a;e[cnt].nx=head[b];head[b]=cnt;
}
void push_up(int p)
{
    sum[p]=sum[ls(p)]+sum[rs(p)];
}
void build(int p,int l,int r)
{
    lg[p]=-1;
    if (l==r) 
    {
        sum[p]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    push_up(p);
}
void push_down(int p,int lenn)
{
    if (lg[p]==-1) return;
    lg[ls(p)]=lg[p];
    lg[rs(p)]=lg[p];
    sum[ls(p)]=lg[p]*(lenn-(lenn>>1));
    sum[rs(p)]=lg[p]*(lenn>>1);
    lg[p]=-1;
}
void update(int p,int l,int r,int nl,int nr,int k)
{
    if (nl<=l&&r<=nr)
    {
        sum[p]=(r-l+1)*k;
        lg[p]=k;
        return;
    }
    push_down(p,(r-l+1));
    int mid=(l+r)>>1;
    if (nl<=mid) update(ls(p),l,mid,nl,nr,k);
    if (nr>mid) update(rs(p),mid+1,r,nl,nr,k);
    push_up(p);
}
void query(int p,int l,int r,int xl,int xr)
{
    if (xl<=l&&r<=xr) 
    {
        res+=sum[p];
        return;
    }
    push_down(p,(r-l+1));
    int mid=(l+r)>>1;
    if (xl<=mid) query(ls(p),l,mid,xl,xr);
    if (xr>mid) query(rs(p),mid+1,r,xl,xr);
}
void dfs1(int x,int f,int deep)
{
    dep[x]=deep;
    fa[x]=f;
    size[x]=1;
    int maxson=-1;
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (y==fa[x]) continue;
        dfs1(y,x,deep+1);
        size[x]+=size[y];
        if (size[y]>maxson) {son[x]=y;maxson=size[y];}
    }
}
void dfs2(int x,int topf)
{
    id[x]=++tot;
    top[x]=topf;
    if (!son[x]) return;
    dfs2(son[x],topf);
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}
int queson(int x)
{
    int ans=0;
    res=0;
    query(1,1,n,id[x],id[x]+size[x]-1);
    ans=res;
    return ans;
}
int querange(int x,int y)
{
    int ans=0;
    while (top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        res=0;
        query(1,1,n,id[top[x]],id[x]);
        ans+=res;
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    res=0;
    query(1,1,n,id[x],id[y]);
    ans+=res;
    return ans;
}
void uprange(int x,int y,int k)
{
    while (top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    update(1,1,n,id[x],id[y],k);
}
int main()
{
    scanf("%d",&n);
    root=1;
    for (int i=1;i<=n-1;i++) 
    {
        int x; scanf("%d",&x);
        x++;
        add_edge(x,i+1);
    }
    dfs1(root,0,1);
    dfs2(root,root);
    build(1,1,n);
    scanf("%d",&m);
    string s;int x;
    for (int i=1;i<=m;i++)
    {
        cin>>s;
        scanf("%d",&x);
        x++;
        if (s=="install") {printf("%d\n",querange(x,root));uprange(x,root,0);}
        if (s=="uninstall") {printf("%d\n",size[x]-queson(x));update(1,1,n,id[x],id[x]+size[x]-1,1);}
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Hale522520/p/10623528.html