Problem:
Range Query on a Tree II

Write a program which manipulates a weighted rooted tree $T$ with the following operations:

$add(v,w)$: add $w$ to all edges from the root to node $u$

$getSum(u)$: report the sum of weights of all edges from the root to node $u$

The given tree $T$ consists of $n$ nodes and every node has a unique ID from $0$ to $n-1$ respectively where ID of the root is $0$.
Note that all weights are initialized to zero.

Input

The input is given in the following format.

$n$

$node_0$

$node_1$

$node_2$

$:$

$node_{n-1}$

$q$

$query_1$

$query_2$

$:$

$query_{q}$

The first line of the input includes an integer $n$, the number of nodes in the tree.

In the next $n$ lines,the information of node $i$ is given in the following format:

ki c1 c2 ... ck

$k_i$ is the number of children of node $i$, and $c_1$ $c_2$ ... $c_{k_i}$ are node IDs of 1st, ... $k$th child of node $i$.

In the next line, the number of queries $q$ is given. In the next $q$ lines, $i$th query is given in the following format:

0 v w

or

1 u

The first integer represents the type of queries.'0' denotes $add(v, w)$ and '1' denotes $getSum(u)$.

Constraints

All the inputs are given in integers

$ 2 \leq n \leq 100000 $

$ c_j < c_{j+1} $   $( 1 \leq j \leq k-1 )$

$ 2 \leq q \leq 200000 $

$ 1 \leq u,v \leq n-1 $

$ 1 \leq w \leq 10000 $

Output

For each $getSum$ query, print the sum in a line.

Sample Input 1

6
2 1 2
2 3 5
0
0
0
1 4
7
1 1
0 3 10
1 2
0 4 20
1 3
0 5 40
1 4

Sample Output 1

0
0
40
150

Sample Input 2

4
1 1
1 2
1 3
0
6
0 3 1000
0 2 1000
0 1 1000
1 1
1 2
1 3

Sample Output 2

3000
5000
6000

Solution in C++ (judge verdict: Accepted)

#include<bits/stdc++.h>
using namespace std;
#define int long long 
int p[100010];
vector<int> G[100010];
int wpath[100010];
int gw[100010];
int dfs_n[100010];
int n_dfs[100010];
int par[100010]; 

struct Lazseg{
  static const int MAX=1<<18;
  int n;
  int dat[2*MAX-1],laz[2*MAX-1];
  Lazseg(){}
  Lazseg(int n_){
    init(n_);
  }
  void init(int n_){
    n=1;
    while(n<n_)n*=2;
    for(int i=0;i<2*n-1;i++)
      dat[i]=laz[i]=0;
  }
  inline void eval(int len,int k){
    if(k*2-1<n*2-1){
      laz[k*2+1]+=laz[k];
      laz[k*2+2]+=laz[k];
    }
    dat[k]+=laz[k]*len;
    laz[k]=0;
  }
  int update(int a,int b,int x,int k,int l,int r){
      eval(r-l,k);
      if(r<=a||b<=l) return dat[k]+laz[k]*(r-l);
      if(a<=l&&r<=b) return dat[k]+(laz[k]+=x)*(r-l);
      eval(r-l,k);
      return dat[k]=update(a,b,x,k*2+1,l,(l+r)/2)+update(a,b,x,k*2+2,(l+r)/2,r);
     
  }
  int query(int a,int b,int k,int l,int r){
    eval(r-l,k);
    if(r<=a||b<=l) return 0;
    if(a<=l&&r<=b) return dat[k];
    int vl=query(a,b,k*2+1,l,(l+r)/2);
    int vr=query(a,b,k*2+2,(l+r)/2,r);
    return vl+vr;
  }
};


int rec_w(int k){
  int sum=1;
  int maw=0;
  int man;
  for(int i=0;i<G[k].size();i++){
    int w=rec_w(G[k][i]);
    if(maw<w)maw=w,man=G[k][i];
    sum+=w;
  }
  if(sum==1)return sum;
  wpath[man]=1;
  gw[k]=man;
  return sum;
}

int used[100010];
void nab(int k){
  if(used[k])return;
  used[k]=1;
  static int s=0;
  n_dfs[k]=s;
  dfs_n[s++]=k;
  if(wpath[k]){
    par[n_dfs[k]]=par[n_dfs[p[k]]];
  }
  nab(gw[k]);
  for(int i=0;i<G[k].size();i++){
    if(G[k][i]==gw[k])continue;
    nab(G[k][i]);
  }
}
Lazseg ls(100010);
signed main(){
  p[0]=-1;
  int n;
  cin>>n;
  for(int i=0;i<n;i++){
    par[i]=i;
    int k;
    cin>>k;
    for(int j=0;j<k;j++){
      int c;
      cin>>c;
      G[i].push_back(c);
      p[c]=i;
    }
  }
  rec_w(0);
  nab(0);
  int q;
  cin>>q;
  for(int i=0;i<q;i++){
    int a;
    cin>>a;
    if(a){
      int u;
      cin>>u;
      u=n_dfs[u];
      int sum=0;
      while(u>0){
	sum+=ls.query(par[u]-1,u,0,0,ls.n);
	u=n_dfs[p[dfs_n[par[u]]]];
      }
      cout<<sum<<endl;
    }else{
      int v,w;
      cin>>v>>w;
      v=n_dfs[v];
      while(v>0){
	ls.update(par[v]-1,v,w,0,0,ls.n);
	v=n_dfs[p[dfs_n[par[v]]]];
      }
    }
  }
  return 0;
}