zoukankan      html  css  js  c++  java
  • FZU2277 Change(dfs序+树状数组)

    传送门

    题意

    q次操作,操作有两种:
    1 v x k:a[v]+=x,a[v']+=x-k(v'是v的子节点)...
    2 v:查询(a[v]mod(10^9+7))

    分析

    子节点增加的值为(x+dep[v]*k-dep[s]*k),那么维护两个值x+dep[v]*k与-k,用两个树状数组维护这两个值,做到区间修改,单点查询。在处理之前需要处理出该树的dfs序,具体见代码

    trick

    1.注意爆int

    代码

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    #define ll long long
    #define F(i,a,b) for(int i=a;i<=b;++i)
    #define R(i,a,b) for(int i=a;i<b;++i)
    const int mod = 1e9+7;
    const int N = 300300;
    
    int l[N],r[N],dep[N];
    int a[N],b[N];
    int t,n,q,judge,vv,x,k;
    int loc;
    vector<int>v[N];
    
    void dfs(int u,int depth)//处理出dfs序与每个点的深度
    {
       dep[u]=depth;
       l[u]=(++loc);
       int sz=v[u].size();
       R(i,0,sz)
       {
          dfs(v[u][i],depth+1);
       }
       r[u]=loc;
    }
    //差分思想
    void adda(int x,int y)//维护x+dep[v]*k
    {
       for(int i=x;i<=n;i+=(i&-i)) a[i]=(a[i]+y)%mod;
    }
    
    void addb(int x,int y)维护-k
    {
       for(int i=x;i<=n;i+=(i&-i)) b[i]=(b[i]+y)%mod;
    }
    
    int sum(int x,int y)//单点查询,仔细思考
    {
       int ret=0,ans=0;
       for(int i=x;i;i-=(i&-i)) ret=(ret*1LL+a[i])%mod;
       for(int i=x;i;i-=(i&-i)) ans=(ans*1LL+b[i])%mod;
       ans=ans*1LL*dep[y]%mod;
       return (ret+ans)%mod;
    }
    
    int main()
    {
       for(scanf("%d",&t);t--;)
       {
          scanf("%d",&n);
          F(i,2,n)
          {
             scanf("%d",&x);
             v[x].push_back(i);
          }
          loc=0;
          dfs(1,1);
          F(i,0,n) a[i]=b[i]=0;
          for(scanf("%d",&q);q--;)
          {
             scanf("%d %d",&judge,&vv);
             if(judge==1)
             {
                scanf("%d %d",&x,&k);
                int ret=(x+dep[vv]*1LL*k)%mod;
                adda(l[vv],ret);
                adda(r[vv]+1,-ret+mod);
                addb(l[vv],(-k+mod)%mod);
                addb(r[vv]+1,k%mod);
             }
             else
             {
                printf("%d
    ",sum(l[vv],vv));
             }
          }
          F(i,1,n) v[i].clear();
       }
    }
    
  • 相关阅读:
    Python资源大全中文版
    Python数据结构之字符串
    一头扎进Node系列
    MySQL的安装配置与卸载
    编程日常单词
    ping请求找不到主机 请检查该名称
    Node项目日志管理
    Node版本控制利器
    JavaScript 数据去重的常用几种方法
    一头扎进Node(一)
  • 原文地址:https://www.cnblogs.com/chendl111/p/7224769.html
Copyright © 2011-2022 走看看