题目大意

给定一棵以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]$

 //minamoto
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(ll x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=,mod=1e9+;
int ver[N],head[N],Next[N],dep[N];
int ls[N],rs[N];
ll c[][N];
int n,tot,q,cnt;
inline void add(int x,ll val,int k){
for(int i=x;i<=n;i+=i&(-i))
(c[k][i]+=val)%=mod;
}
inline ll sum(int x){
ll a=,b=;
for(int i=ls[x];i;i-=i&(-i)){
a+=c[][i],b+=c[][i];
}
return ((a-b*dep[x])%mod+mod)%mod;
}
void dfs(int u,int fa){
ls[u]=++cnt;
dep[u]=dep[fa]+;
for(int i=head[u];i;i=Next[i]) dfs(ver[i],u);
rs[u]=cnt;
}
int main(){
//freopen("testdata.in","r",stdin);
n=read();
for(int i=;i<=n;++i){
int fa=read();
ver[++tot]=i,Next[tot]=head[fa],head[fa]=tot;
}
dfs(,);
q=read();
while(q--){
int opt=read(),v=read();
if(opt&) print(sum(v));
else{
ll x=read(),k=read();
add(ls[v],x+dep[v]*k,);
add(rs[v]+,-x-dep[v]*k,);
add(ls[v],k,);
add(rs[v]+,-k,);
}
}
Ot();
return ;
}

CodeForces - 396C On Changing Tree(树状数组)的更多相关文章

  1. CodeForces 396C On Changing Tree

    On Changing Tree Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces ...

  2. codeforces#1167F. Scalar Queries(树状数组+求贡献)

    题目链接: https://codeforces.com/contest/1167/problem/F 题意: 给出长度为$n$的数组,初始每个元素为$a_i$ 定义:$f(l, r)$为,重排$l$ ...

  3. HDU3333 Turing Tree 树状数组+离线处理

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. POJ 3321 Apple Tree(树状数组)

                                                              Apple Tree Time Limit: 2000MS   Memory Lim ...

  5. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  6. POJ--3321 Apple Tree(树状数组+dfs(序列))

    Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 22613 Accepted: 6875 Descripti ...

  7. CodeForces 828E DNA Evolution(树状数组)题解

    题意:给你一个串k,进行两个操作: “1 a b”:把a位置的字母换成b “2 l r s”:求l到r有多少个字母和s匹配,匹配的条件是这样:从l开始无限循环s形成一个串ss,然后匹配ss和指定区间的 ...

  8. Codeforces 909C Python Indentation:树状数组优化dp

    题目链接:http://codeforces.com/contest/909/problem/C 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现. 现在有一种简化版的Pytho ...

  9. gym 100589A queries on the Tree 树状数组 + 分块

    题目传送门 题目大意: 给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重. 思路: 思考后发现,以dfs序建立树状数 ...

随机推荐

  1. gvim

    [gvim] 1.gvim的配置文件在安装目录下,文件名为_vimrc. 2.通过以下命令选择配色方案:

  2. ubuntu tensorflow cpu Faster-RCNN配置参考

    https://blog.csdn.net/qq_36652619/article/details/85006559     (参考) https://blog.csdn.net/zcy0xy/art ...

  3. [c++] How many bytes do pointers take up?

    How many bytes do pointers take up? on 16 bit systems take up 2 bytes on 32 bit systems take up 4 by ...

  4. MP3 Lame 转换 参数 设置(转)

    我们在对音频格式的转换中,打交道最多的就是MP3了.如果你能彻底玩转MP3,那么对你的音频创作和对其他音频格式的掌握会有很大的帮助.下面我们给大家介绍MP3制作软件:LAME 要制作出高音质的MP3靠 ...

  5. [GO]结构体指针类型匿名字段

    package main import "fmt" type Person struct { name string sex byte age int } type Student ...

  6. C++中的深拷贝和浅拷贝 QT中的深拷贝,浅拷贝和隐式共享

    下面是C++中定义的深,浅拷贝 当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用.也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用.以下情况都会 ...

  7. javascript总结41:表格全选反选,经典案例详解

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. CodeForces 540A Combination Lock (水题)

    题意:给定一个串数,表示一种密码锁,再给定一串密码,问你滑动最少的次数,把第一行变成第二行. 析:很简单么,反正只有0-9这个10个数字,那么就是把每一个数从正着滑和倒着滑中找出一个最小的即可,正着滑 ...

  9. Web大文件上传(断点续传)控件-Xproer.HttpUploader6-安装教程

      安装教程: IE8控件安装教程 IE9控件安装教程 Firefox控件安装教程 Chrome控件安装教程 Chrome 45+控件安装教程 相关问题: 提示Runtime Error错误 360拦 ...

  10. ObjC正则表达式验证

    试过ObjC的regkit这个框架. 也用过内置的正则表达式验证. 最后发现有个非常简单的方法就可以做到验证正则表达式.那就是NSPredicte这个类提供的方法. 这里有验证邮箱地址的正则为例: N ...