• CodeForces


    题目大意

    给定一棵以1为根的树,初始时所有点为0

    给出树的方式是从节点2开始给出每一个点的父亲

    然后是 $m$ 次操作,分为两种

    $1 v,k,x$ 表示在以v为根的子树中的每一个点上添加 $x-i*k$( $i$ 表示节点与 $v$ 的距离)(包括点 $v$ )

    $2 v$ 查询节点 $v$ 的值

    输出每一个2操作的答案模 $1e9+7$ 的值

    题解

    话说真没想到这题竟然这么简单……死活都想不出来……

    先dfs预处理出每一个节点的dfs序,以及子树代表的区间$ls$和$rs$,以及每一个点的深度$dep$

    假设先$add(ls[v],x+dep[v]*k),add(rs[v]+1,-x-dep[v]*k)$,然后用树状数组维护前缀和,树状数组设为$c1$

    可以发现,$v$这个点多加去了$dep[v]*k$,要减掉。同理可得,$v$的所有子树都要减掉$dep[j]*k$($j$为$v$的子节点)

    可以证明以上这么乱搞之后每一个点的值都加上了正确的数

    证:$j$节点经过这一操作后加上了$dep[v]*k-dep[j]*k=k*(dep[j]-dep[v])=k*dis[v,j]$

    然后证明每一个节点都加上了正确的数值

    那么只要再开一个树状数组维护前缀$k$就可以了

    查询的答案就是$sum(ls[v],c1)-sum(ls[v],c2)*dep[v]$

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #define ll long long
     5 using namespace std;
     6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     7 char buf[1<<21],*p1=buf,*p2=buf;
     8 inline int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 char sr[1<<21],z[20];int C=-1,Z;
    19 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    20 inline void print(ll x){
    21     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    22     while(z[++Z]=x%10+48,x/=10);
    23     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    24 }
    25 const int N=300005,mod=1e9+7;
    26 int ver[N],head[N],Next[N],dep[N];
    27 int ls[N],rs[N];
    28 ll c[2][N];
    29 int n,tot,q,cnt;
    30 inline void add(int x,ll val,int k){
    31     for(int i=x;i<=n;i+=i&(-i))
    32     (c[k][i]+=val)%=mod;
    33 }
    34 inline ll sum(int x){
    35     ll a=0,b=0;
    36     for(int i=ls[x];i;i-=i&(-i)){
    37         a+=c[0][i],b+=c[1][i];
    38     }
    39     return ((a-b*dep[x])%mod+mod)%mod;
    40 }
    41 void dfs(int u,int fa){
    42     ls[u]=++cnt;
    43     dep[u]=dep[fa]+1;
    44     for(int i=head[u];i;i=Next[i]) dfs(ver[i],u);
    45     rs[u]=cnt;
    46 }
    47 int main(){
    48     //freopen("testdata.in","r",stdin);
    49     n=read();
    50     for(int i=2;i<=n;++i){
    51         int fa=read();
    52         ver[++tot]=i,Next[tot]=head[fa],head[fa]=tot;
    53     }
    54     dfs(1,0);
    55     q=read();
    56     while(q--){
    57         int opt=read(),v=read();
    58         if(opt&2) print(sum(v));
    59         else{
    60             ll x=read(),k=read();
    61             add(ls[v],x+dep[v]*k,0);
    62             add(rs[v]+1,-x-dep[v]*k,0);
    63             add(ls[v],k,1);
    64             add(rs[v]+1,-k,1);
    65         }
    66     }
    67     Ot();
    68     return 0;
    69 }
  • 相关阅读:
    [翻译] AAPullToRefresh
    [翻译] DKTagCloudView
    【转】Data URL和图片,及Data URI的利弊
    【转】C#获取当前日期时间(转)
    【转】Android的setTag
    【转】Android之Adapter用法总结
    【转】jpg png区别和使用
    【转】Android UI开发第三十一篇——Android的Holo Theme
    【转】android中的Style与Theme
    【转】关于Eclipse创建Android项目时,会多出一个appcompat_v7的问题
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9456692.html
Copyright © 2020-2023  润新知