Rooted Tree
Difficulty: Hard

You are given a rooted [tree](http://en.wikipedia.org/wiki/Tree_(graph_theory)) with _N_ nodes and the root of the tree, _R_, is also given. Each node of the tree contains a value, that is initially empty. You have to mantain the tree under two operations:

1. Update Operation
2. Report Operation

**Update Operation**  
Each Update Operation begins with the character `U`. Character `U` is followed by 3 integers _T, V and K_. For every node which is the descendent of the node _T_, update it's value by adding _V + d\*K_, where _V_ and _K_ are the parameters of the query and _d_ is the distance of the node from _T_. Note that _V_ is added to node _T_.  

**Report Operation**  
Each Report Operation begins with the character `Q`. Character `Q` is followed by 2 integers, _A_ and _B_. Output the sum of values of nodes in the path from _A_ to _B_ modulo _(10<sup>9</sup> + 7)_  

**Input Format**  
The first Line consists of 3 space separated integers, _N E R_, where _N_ is the number of nodes present, _E_ is the total number of queries (update + report), and _R_ is root of the tree.  

Each of the next _N-1_ lines contains 2 space separated integers, _X_ and _Y_ (_X_ and _Y_ are connected by an edge).

Thereafter, _E_ lines follows: each line can represent either the Update Operation or the Report Operation.<br>

- _Update Operation_ is of the form : _U T V K_.
- _Report Operation_ is of the form : _Q A B_.

**Output Format**  
Output the answer for every given report operation.

**Constraints**  

1 &le; N, E &le; 10<sup>5</sup>  
1 &le; E &le; 10<sup>5</sup>  
1 &le; R, X, Y, T, A, B &le; N  
1 &le; V, K &le; 10<sup>9</sup>  
X &ne; Y

**Sample Input**

    7 7 1
    1 2
    2 3
    2 4
    2 5
    5 6
    6 7
    U 5 10 2
    U 4 5 3
    Q 1 7
    U 6 7 4
    Q 2 7
    Q 1 4
    Q 2 4

**Sample Output**

    36
    54
    5
    5

**Explanation**  

- Values of Nodes after `U 5 10 2`: `[0 0 0 0 10 12 14]`.
- Values of Nodes after `U 4 5 3`: `[0 0 0 5 10 12 14]`. 
- Sum of the Nodes from 1 to 7: 0 + 0 + 10 + 12 + 14 = 36.
- Values of Nodes after `U 6 7 4`: [0 0 0 5 10 19 25].  
- Sum of the Nodes from 2 to 7: 0 + 10 + 19 + 25 = 54. 
- Sum of the Nodes from 1 to 4: 0 + 0 + 5 = 5.
- Sum of the Nodes from 2 to 4: 0 + 5 = 5.

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:


Reference solution (C++):
    #ifdef ssu1
    #define _GLIBCXX_DEBUG
    #endif
    #undef NDEBUG

    #include <algorithm>
    #include <functional>
    #include <numeric>
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstring>
    #include <cassert>
    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <deque>
    #include <queue>
    #include <bitset>
    #include <sstream>

    using namespace std;

    #define fore(i, l, r) for(int i = (l); i < (r); ++i)
    #define forn(i, n) fore(i, 0, n)
    #define fori(i, l, r) fore(i, l, (r) + 1)
    #define sz(v) int((v).size())
    #define all(v) (v).begin(), (v).end()
    #define pb push_back
    #define mp make_pair
    #define X first
    #define Y second

    #if ( _WIN32 || __WIN32__ )
       #define LLD "%I64d"
    #else
       #define LLD "%lld"
    #endif

    typedef long long li;
    typedef long double ld;
    typedef pair<int, int> pt;

    template<typename T> T abs(T a) { return a < 0 ? -a : a; }
    template<typename T> T sqr(T a) { return a*a; }

    const int INF = (int)1e9;
    const ld EPS = 1e-9;
    const ld PI = 3.1415926535897932384626433832795;

    int readInt(int l, int r){
       int x;
       if(scanf("%d", &x) != 1){
           fprintf(stderr, "Expected int in range [%d, %d], but haven't found!", l, r);
           throw;
       }
       if(!(l <= x && x <= r)){
           fprintf(stderr, "Expected int in range [%d, %d], but found %d!", l, r, x);
           throw;
       }
       return x;
    }

    const int NMAX = 300000;
    const int LOG = 20;
    const int mod = 1000000000 + 7;

    int n, q, root, used[NMAX];
    vector<int> g[NMAX];
    int dep[NMAX], p[NMAX][LOG], lf[NMAX], rg[NMAX], mul[3][NMAX], timer = 0;

    void dfs(int v, int pv){
       used[v] = 1;
       dep[v] = (v == pv ? 0 : dep[pv] + 1);
       lf[v] = rg[v] = timer++;

       p[v][0] = pv;
       fore(lev, 1, LOG){
           p[v][lev] = p[p[v][lev - 1]][lev - 1];
       }

       forn(i, sz(g[v])){
           int u = g[v][i];
           if(u == pv)
               continue;
           dfs(u, v);
           rg[v] = rg[u];
       }
    }

    int lca(int a, int b){
       if(dep[a] < dep[b])
           swap(a, b);
       forn(i, LOG){
           if((dep[a] - dep[b]) & (1 << i)){
               a = p[a][i];
           }
       }
       for(int i = LOG - 1; i >= 0; --i){
           if(p[a][i] != p[b][i]){
               a = p[a][i];
               b = p[b][i];
           }
       }
       if(a != b)
           a = p[a][0], b = p[b][0];
       assert(a == b);
       return a;
    }

    inline void norm(int& v){
       while(v < 0)
           v += mod;
       while(v >= mod)
           v -= mod;
    }

    int modpow(int a, int b){
       int ans = 1 % mod;
       while(b){
           if(b & 1)
               ans = (ans * li(a)) % mod;
           a = (a * li(a)) % mod;
           b >>= 1;
       }
       return ans;
    }

    inline int rev(int a){
       return modpow(a, mod - 2);
    }

    inline int doMod(li v){
       return (int)((v % mod + mod) % mod);
    }

    void upd(int t[NMAX], int i, int v){
       for(; i < NMAX; i = (i | (i + 1))){
           t[i] += v;
           norm(t[i]);
       }
    }

    int sum(int t[NMAX], int r){
       int ans = 0;
       for(; r >= 0; r = (r & (r + 1)) - 1){
           ans += t[r];
           norm(ans);
       }
       return ans;
    }

    int sum(int t[NMAX], int l, int r){
       int ans = sum(t, r) - sum(t, l - 1);
       norm(ans);
       return ans;
    }

    int get(int a){
       int pw = 1, ans = 0;
       forn(i, 3){
           ans = (ans + sum(mul[i], 0, lf[a]) * 1LL * pw) % mod;
           pw = (pw * 1LL * dep[a]) % mod;
       }
       return ans;
    }

    int dist(int a, int b){
       int mid = lca(a, b);

       int ans = get(a) + get(b) - 2 * get(mid);
       norm(ans);
       if(mid == root)
           ans += get(mid);
       else
           ans += get(mid) - get(p[mid][0]);
       norm(ans);
       return ans;
    }

    void rangeupd(int t[NMAX], int l, int r, int val){
       upd(t, l, val);
       upd(t, r + 1, doMod(mod - val));
    }

    void doUpdQuery(int t, int V, int U){
       int L = lf[t], R = rg[t], x = V;
       rangeupd(mul[0], L, R, doMod((1 - dep[t]) * li(x)));
       rangeupd(mul[1], L, R, x);
       x = U;
       rangeupd(mul[0], L, R, doMod(-(1 - dep[t]) * 1LL * doMod(x * 1LL * dep[t])));
       rangeupd(mul[1], L, R, doMod(-x * 1LL * dep[t]));

       rangeupd(mul[1], L, R, doMod(-x * 1LL * dep[t] + x));
       rangeupd(mul[2], L, R, x);
       x = doMod(-x * 1LL * rev(2));
       rangeupd(mul[0], L, R, doMod(((dep[t] * 1LL * dep[t] - dep[t]) % mod) * li(x)));
       rangeupd(mul[1], L, R, doMod((-2 * dep[t] + 1) * li(x)));
       rangeupd(mul[2], L, R, x);
    }

    int main(){
    #ifdef ssu1
       assert(freopen("input.txt", "rt", stdin));
       //assert(freopen("output.txt", "wt", stdout));
    #endif
       n = readInt(1, 100000);
       q = readInt(1, 100000);
       root = readInt(1, n) - 1;

       forn(i, n - 1){
           int a, b;
           a = readInt(1, n) - 1;
           b = readInt(1, n) - 1;
           g[a].pb(b);
           g[b].pb(a);
       }

       dfs(root, root);
       forn(v, n){
           assert(used[v]);
       }

       forn(qi, q){
           char type;
           assert(scanf(" %c ", &type) == 1);
           assert(type == 'Q' || type == 'U');
           if(type == 'Q'){
               int a, b;
               a = readInt(1, n) - 1;
               b = readInt(1, n) - 1;
               printf("%d\n", dist(a, b));
           }else{
               int t, v, k;
               t = readInt(1, n) - 1;
               v = readInt(1, 1000000000);
               k = readInt(1, 1000000000);
               doUpdQuery(t, v, k);
           }
       }
       return 0;
    }