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;
    }
  • 相关阅读:
    CF343D Water Tree
    CF340B Maximal Area Quadrilateral
    测试环境/生产环境,接口地址配置
    json-server MOCK方案
    vscode prettier保存代码时自动格式化
    蓝鲸6.0前置准备
    nginx日志提取案列
    蓝鲸模拟考试
    部署维护
    第一次模拟考
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7241861.html
Copyright © 2011-2022 走看看