codeforces396C
On Changing Tree
You are given a rooted tree consisting of n vertices numbered from 1 to n. The root of the tree is a vertex number 1.
Initially all vertices contain number 0. Then come q queries, each query has one of the two types:
- The format of the query: 1 v x k. In response to the query, you need to add to the number at vertex v number x; to the numbers at the descendants of vertex vat distance 1, add x - k; and so on, to the numbers written in the descendants of vertex v at distance i, you need to add x - (i·k). The distance between two vertices is the number of edges in the shortest path between these vertices.
- The format of the query: 2 v. In reply to the query you should print the number written in vertex v modulo 1000000007 (109 + 7).
Process the queries given in the input.
Input
The first line contains integer n (1 ≤ n ≤ 3·105) — the number of vertices in the tree. The second line contains n - 1 integers p2, p3, ... pn (1 ≤ pi < i), where pi is the number of the vertex that is the parent of vertex i in the tree.
The third line contains integer q (1 ≤ q ≤ 3·105) — the number of queries. Next qlines contain the queries, one per line. The first number in the line is type. It represents the type of the query. If type = 1, then next follow space-separated integers v, x, k (1 ≤ v ≤ n; 0 ≤ x < 109 + 7; 0 ≤ k < 109 + 7). If type = 2, then next follows integer v (1 ≤ v ≤ n) — the vertex where you need to find the value of the number.
Output
For each query of the second type print on a single line the number written in the vertex from the query. Print the number modulo 1000000007 (109 + 7).
Examples
3
1 1
3
1 1 2 1
2 1
2 2
2
1
Note
You can read about a rooted tree here: http://en.wikipedia.org/wiki/Tree_(graph_theory).
给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点;
然后是m次操作,操作分为两种,1 v, x, k,表示在以v为根的子树上添加,添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;2 v查询节点v的值。
sol:把dfs序搞出来了以后,区间操作就是子树操作,然后两个都是经典操作,对于1操作,先加上Depth[v]*k,再对查询的点p减去Depth[p]*k
/* 给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点; 然后是m次操作,操作分为两种,1 v, x, k,表示在以v为根的子树上添加, 添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;2 v查询节点v的值。 */ #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') const int N=300005,M=600005; const ll Mod=1000000007; int n,Q; inline void Ad(ll &x,ll y) { x+=y; x-=(x>=Mod)?Mod:0; x+=(x<0)?Mod:0; } namespace Tree { int tot=0,Next[M],to[M],head[N]; inline void add(int x,int y) { Next[++tot]=head[x]; to[tot]=y; head[x]=tot; } int In[N],Out[N],cnt=0,Depth[N]; inline void dfs(int x) { int i; In[x]=++cnt; for(i=head[x];i;i=Next[i]) Depth[to[i]]=Depth[x]+1,dfs(to[i]); Out[x]=++cnt; } struct segment { ll S[N<<1]; #define lowbit(x) ((x)&(-x)) inline void Ins(int x,int Val) { while(x<=cnt) { Ad(S[x],Val); x+=lowbit(x); } } inline int Que(int x) { ll ans=0; while(x>0) { Ad(ans,S[x]); x-=lowbit(x); } return ans; } }SGT[2]; inline void Solve() { int i; Depth[1]=0; dfs(1); R(Q); while(Q--) { ll opt,rt,Val,Del; R(opt); R(rt); if(opt==1) { Val=read()%Mod; R(Del); SGT[0].Ins(In[rt],(Val+Del*Depth[rt]%Mod)%Mod); SGT[0].Ins(Out[rt]+1,(-1)*(Val+Del*Depth[rt]%Mod)%Mod); SGT[1].Ins(In[rt],Del); SGT[1].Ins(Out[rt]+1,(-1)*Del); } else { ll tmp,oo; tmp=SGT[0].Que(In[rt]); oo=SGT[1].Que(In[rt]); Ad(tmp,(-1)*oo*Depth[rt]%Mod); Wl(tmp); } } } } #define T Tree int main() { int i; R(n); for(i=2;i<=n;i++) { int x=read(); T::add(x,i); } T::Solve(); return 0; } /* Input 3 1 1 3 1 1 2 1 2 1 2 2 Output 2 1 Input 10 1 2 3 4 4 3 3 6 7 10 1 6 13 98 1 7 17 66 1 5 32 39 1 1 9 5 1 7 27 11 1 1 24 79 1 5 87 86 2 2 1 5 9 38 2 5 Output 999999956 999999832 */