zoukankan      html  css  js  c++  java
  • 【BZOJ 4034】[HAOI2015]树上操作 差分+dfs序+树状数组

    我们只要看出来这道题 数组表示的含义就是 某个点到根节点路径权值和就行 那么我们可以把最终答案 看做 k*x+b x就是其深度 ,我们发现dfs序之后,修改一个点是差分一个区间,修改一个点的子树,可以看做对于子树中的每一个点进行 a*(deep[x]-deep[root]+1) root是子树根节点,那么我们对 k 用a差分区间 对b用 -a*(deep[root]-1)差分区间

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    typedef long long LL;
    LL k[MAXN],b[MAXN];
    int n,m;
    inline LL sum_k(int x)
    {
        LL sum=0;
        while(x>0) sum+=k[x],x-=x&(-x);   
        return sum;       
    }
    inline void ins_k(int x,LL key)
    {
        while(x<=n) k[x]+=key,x+=x&(-x);
    }
    inline LL sum_b(int x)
    {
        LL sum=0;
        while(x>0) sum+=b[x],x-=x&(-x);
        return sum;
    }
    inline void ins_b(int x,LL key)
    {
        while(x<=n) b[x]+=key,x+=x&(-x);
    } 
    int l[MAXN],r[MAXN];
    struct VIA
    {
        int to,next;
    }c[MAXN<<1];
    int head[MAXN],t,Ti,deep[MAXN];
    inline void add(int x,int y)
    {
      c[++t].to=y;
      c[t].next=head[x];
      head[x]=t;
    }
    void dfs(int x)
    {
       l[x]=++Ti;
       for(int i=head[x];i;i=c[i].next)
       if(l[c[i].to]==0)
       {
         deep[c[i].to]=deep[x]+1;
         dfs(c[i].to);
       }
       r[x]=Ti;
    }
    int temp[MAXN];
    inline void Init()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&temp[i]);
        for(int i=1;i<n;i++)
        {
           int x,y;
           scanf("%d%d",&x,&y);
           add(x,y);
           add(y,x); 
        }
        deep[1]=1;
        dfs(1);
        for(int i=1;i<=n;i++)
         ins_b(l[i],temp[i]),ins_b(r[i]+1,-temp[i]);
    }
    inline void work()
    {
        while(m--)
        {
          int opt,x,a;
          scanf("%d%d",&opt,&x);
          if(opt==1)
          {
            scanf("%d",&a);
            ins_b(l[x],a),ins_b(r[x]+1,-a);
          }else
          if(opt==2)
          {
            scanf("%d",&a);
            ins_k(l[x],a),ins_k(r[x]+1,-a);
            ins_b(l[x],-(LL)a*(deep[x]-1)),ins_b(r[x]+1,(LL)a*(deep[x]-1));
          }else
          {
            LL ans=sum_k(l[x])*deep[x]+sum_b(l[x]);
            printf("%lld
    ",ans);
          }
        }
    }
    int main()
    {
        Init();
        work();
        return 0;
    }
  • 相关阅读:
    如何阅读论文(译)
    Linux运维小知识
    认识Linux分区
    如何获取离线安装Chrome扩展程序的包
    Centos 7.4 下初探Zabbix安装
    尝试在Linux上部署Asp.net Core应用程序
    Centos 7.3下图文安装SQL Server
    Asp.net MVC Razor常见问题及解决方法
    轻量级高性能ORM框架:Dapper高级玩法
    Asp.net MVC 如何对所有用户输入的字符串字段做Trim处理
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7241861.html
Copyright © 2011-2022 走看看