bzoj4196 [Noi2015]软件包管理器——树链剖分

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4196

树链剖分。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=1e5+5;
int n,m,fa[maxn],dfn[maxn],end[maxn],top[maxn],to[maxn],siz[maxn],head[maxn],ct,tim;
struct N{
    int to,next;
    N(int t=0,int n=0):to(t),next(n) {}
}edge[maxn];
struct T{int sum,siz; bool f[3];}t[maxn<<2];
int rd()
{
    int ret=0;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)ret=ret*10+ch-‘0‘,ch=getchar();
    return ret;
}
void dfs(int x)
{
    siz[x]=1;
    for(int i=head[x],u;i;i=edge[i].next)
    {
        dfs(u=edge[i].to);
        if(siz[u]>siz[to[x]])to[x]=u;
        siz[x]+=siz[u];
    }
}
void dfs2(int x)
{
    dfn[x]=++tim;//不在dfs
    if(to[x])top[to[x]]=top[x],dfs2(to[x]);
    for(int i=head[x],u;i;i=edge[i].next)
    {
        if((u=edge[i].to)==to[x])continue;
        top[u]=u; dfs2(u);
    }
    end[x]=tim;
}
void pushup(int x)
{
    int ls=(x<<1),rs=(x<<1|1);
    t[x].siz=t[ls].siz+t[rs].siz;
    t[x].sum=t[ls].sum+t[rs].sum;
}
void pushdown(int x)
{
    if(!t[x].f[0]&&!t[x].f[1])return;
    int ls=(x<<1),rs=(x<<1|1);
    for(int i=0;i<=1;i++)
        if(t[x].f[i])
        {
            t[x].f[i]=0; t[ls].f[i]=1; t[rs].f[i]=1;
            t[ls].f[!i]=0; t[rs].f[!i]=0;
            t[ls].sum=t[ls].siz*i; t[rs].sum=t[rs].siz*i;
        }
}
void build(int x,int l,int r)
{
    if(l==r){t[x].siz=1;return;}
    int mid=((l+r)>>1);
    build(x<<1,l,mid); build(x<<1|1,mid+1,r);
    pushup(x);
}
int query(int x,int l,int r,int L,int R,int val)
{
    if(l>=L&&r<=R)
    {
        if(val)return t[x].sum;
        else return t[x].siz-t[x].sum;
    }
    int mid=((l+r)>>1),ret=0;
    pushdown(x);
    if(mid>=L)ret+=query(x<<1,l,mid,L,R,val);
    if(mid<R)ret+=query(x<<1|1,mid+1,r,L,R,val);
    return ret;
}
void update(int x,int l,int r,int L,int R,int val)
{
    if(l>=L&&r<=R)
    {
        t[x].f[val]=1;  t[x].f[!val]=0;
        t[x].sum=t[x].siz*val; return;
    }
    int mid=((l+r)>>1);
    if(mid>=L)update(x<<1,l,mid,L,R,val);
    if(mid<R)update(x<<1|1,mid+1,r,L,R,val);
    pushup(x);
}
int ask(int x)
{
    int ret=0;
    while(x)
    {
        int l=dfn[top[x]],r=dfn[x];
        ret+=query(1,1,n,l,r,0);
        update(1,1,n,l,r,1);
        x=fa[top[x]];
    }
    return ret;
}
int main()
{
    n=rd();
    for(int i=2;i<=n;i++)
    {
        fa[i]=rd()+1;
        edge[++ct]=N(i,head[fa[i]]);head[fa[i]]=ct;
    }
    dfs(1); top[1]=1; dfs2(1); build(1,1,n);
    m=rd(); char ch[15];
    for(int i=1,x;i<=m;i++)
    {
        scanf("%s",&ch); x=rd()+1;
        if(ch[0]==‘u‘)
        {
            printf("%d\n",query(1,1,n,dfn[x],end[x],1));
            update(1,1,n,dfn[x],end[x],0);
        }
        if(ch[0]==‘i‘)
        {
            printf("%d\n",ask(x));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Zinn/p/9188635.html

时间: 2024-10-11 09:59:55

bzoj4196 [Noi2015]软件包管理器——树链剖分的相关文章

[Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]

题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空.注意边界,编号是从0开始的,容易漏掉树根. 第一次写树剖- 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #inclu

Bzoj 4196: [Noi2015]软件包管理器 树链剖分

4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian

BZOJ4196 [NOI2015] 软件包管理器

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4196,http://uoj.ac/problem/128 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/Cen

[UOJ#128][BZOJ4196][Noi2015]软件包管理器

试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

BZOJ 4196: [Noi2015]软件包管理器

二次联通门 : BZOJ 4196: [Noi2015]软件包管理器 /* BZOJ 4196: [Noi2015]软件包管理器 树链剖分 树链剖分 , 用线段树维护链上的和与子树的和 对于1操作, 每次预先查询待修改点x点的深度 后查询1到x这条链上有多少已安装的, 然后上面的值减下面的值 对于2操作,每次查询以x为根的子树的大小 修改整颗子树即可.. 说白了其实就是板子题 */ #include <cstdio> #define Max 500090 inline int min (int

【BZOJ 4196】[Noi2015]软件包管理器

[Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 331  Solved: 199[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubunt

洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

BZOJ_4196_[Noi2015]软件包管理器_树链剖分

题意: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那么

【NOI2015】【BZOJ4196】软件包管理器

Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依