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++):
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<iostream>
    #include<string.h>
    #include<vector>
    #include<set>
    #include<map>
    #include<utility>
    #include<bitset>
    #include<queue>
    #include<stack>
    #include<assert.h>

    using namespace std;

    #define mod 1000000007

    typedef long long int ll;

    //Variables required for HL tree
    int which[100001],size_sub[100001],parent[100001],depth[100001],seg_size,mapping[100001],counter,skip[100001],N,root,visit[100001],level;
    bool hlson[100001];
    vector<int> myvector[100001];
    const ll inv = 500000004;

    int power[25];
    void constant()
    {
        power[0]=1;
        for(int i=1;i<=25;i++)	power[i]=power[i-1]<<1;
    }
    int obtain(int x)
    {
        int l=0,y=x;
        while(x!=0){
            l++;
            x>>=1;
        }
        if(power[l-1]!=y)	l++;
        return l;
    }
    struct node{
        ll v,vx,d,dx,xxd;
        node(ll a=0,ll b=0,ll c=0,ll e=0, ll f=0){
            v=a;
            vx=b;
            d=c;
            dx=e;
            xxd=f;
        }
        node operator + (const node &x)const{
            return node( (x.v+v)%mod , (x.vx+vx)%mod , (x.d+d)%mod, (x.dx+dx)%mod , (x.xxd+xxd)%mod );
        }
        node operator % (int m) const{
            return node( v%m , vx%m , d%m , dx%m , xxd%m );
        }
    }HL[1<<18],freq[100001];

    /*********************************FOR FINDING LCA***********************************/
    int Root[100001][18],store[100001];
    void init()
    {
        store[0]=0;store[1]=0;store[2]=1;
        int cmp=4;
        for(int i=3;i<=100000;i++){
            if(cmp>i)       store[i]=store[i-1];
            else{
                store[i]=store[i-1]+1;
                cmp<<=1;
            }
        }
    }
    void process(int N)
    {
        memset(Root,-1,sizeof(Root));
        for(int i=1;i<=N;i++)	Root[i][0]=parent[i];
        for(int i=1;(1<<i)<=N;i++)
            for(int j=1;j<=N;j++)
                if(Root[j][i-1]!=-1)
                    Root[j][i]=Root[Root[j][i-1]][i-1];
    }
    int lca(int p,int q)
    {
        int temp;
        if(depth[p]>depth[q])	swap(p,q);
        int steps=store[depth[q]];
        for(int i=steps;i>=0;i--)
            if(depth[q]-(1<<i) >= depth[p])
                q=Root[q][i];
        if(p==q)	return p;
        for(int i=steps;i>=0;i--){
            if(Root[p][i]!=Root[q][i])
                p=Root[p][i],q=Root[q][i];
        }
        return parent[p];
    }
    /*********************************FOR FINDING LCA***********************************/


    /*********************************HL Tree Coding Begins***************************/
    void dfs_pre(int root)
    {
        which[root]=-1;
        skip[root]=root;	//only purpose is to init it!
        size_sub[root]=1;
        for(vector<int>::iterator it=myvector[root].begin();it!=myvector[root].end();it++){
            if(parent[root]==*it)	continue;
            parent[*it]=root;
            depth[*it]=depth[root]+1;
            dfs_pre(*it);
            size_sub[root]+=size_sub[*it];
        }
        for(vector<int>::iterator it=myvector[root].begin();it!=myvector[root].end();it++){
            if(parent[root]==*it)   continue;
            if(size_sub[*it]>size_sub[root]/2){
                hlson[*it]=true;
                which[root]=*it;
            }
            else{
                hlson[*it]=false;
            }
        }
    }
    void dfs_cal(int root)
    {
        int z;
        for(vector<int>::iterator it=myvector[root].begin();it!=myvector[root].end();it++){
            if(parent[root]==*it)	continue;
            if(hlson[*it]){		//heavy node detected
                skip[*it]=skip[root];
                if(skip[root]==root){
                    z=*it;
                    //construction of segment tree begins
                    while(z!=-1){
                        mapping[z]=seg_size;
                        seg_size++;
                        z=which[z];
                    }
                }
            }
            dfs_cal(*it);
        }
    }
    void seg_Update(int l)
    {
        int v;
        while(l!=0){
            v=(l<<1);
            HL[l]=(HL[v]+HL[v+1]);
            l>>=1;
        }
    }
    node seg_Query(int l,int r,int i,int j,int nod)
    {
        int v,mid;
        if(j<l || i>r)	return node();
        if(l>=i && j>=r){
            return HL[nod];
        }
        v=nod<<1;
        mid=(l+r)>>1;
        return seg_Query(l,mid,i,j,v)+seg_Query(mid+1,r,i,j,v+1);
    }
    node HL_Update(int x,node v)
    {
        int ind;
        if(hlson[x]){		//Heavy Part
            ind=mapping[x]+power[level-1];
            HL[ind]=(HL[ind]+v);
            seg_Update(ind>>1);
        }
    }
    node fun(ll x,ll v,ll d)
    {
        x=depth[x];
        return ( node( v,v*x,d,d*x,((x*x-x)%mod)*d )%mod );
    }
    node HL_Query(int i,int j)		//from i to j --> j is the ancestor
    {
        node r;
        int end,st;
        while(i!=j){
            if(hlson[i]){
                end=skip[i];
                st=i;
                i=end;
                end=which[i];
                if(depth[end]<=depth[j]){
                    r=r+seg_Query(1,power[level-1],mapping[j]+1,mapping[st]+1,1);
                    return r;
                }
                else{		//carry on
                    r=r+seg_Query(1,power[level-1],mapping[end]+1,mapping[st]+1,1);
                }
            }
            else{
                r=r+freq[i];
                i=parent[i];
            }
        }
        return ((r+freq[j]));
    }
    /*********************************HL Tree Coding Ends***************************/
    ll part1(node A,ll dep)
    {
        ll ret1 = ( A.v*(dep+1) - A.vx - A.dx*(dep) + A.xxd*(ll)inv )%mod;
        ll ret2 = ( ( A.d*(dep*dep+dep) ) %mod )*(ll)inv ;
        return (ret1+ret2)%mod;
    }
    ll part2(node A,ll a,ll y,ll z)		//a-ances , y-left , z-right
    {
        ll cons = ( a*(y+z-(ll)2*a+(ll)1) + ((y-a)*(y-a+(ll)1))/(ll)2 + ((z-a)*(z-a+(ll)1))/(ll)2 )%mod; 
        return (( (A.v-A.dx)*(y+z-(ll)2*a+(ll)1) + A.d*(cons) ) %mod);
    }
    void solve()
    {
        node A,B,C,D;
        char c;
        int x,y,anc,Q;
        ll s,b,nodes,expr,k,solution;
        memset(freq,0,sizeof(freq));
        scanf("%d%d%d",&N,&Q,&root);
        assert(N<=100000 && N>=1);
        assert(Q<=100000 && Q>=1);
        assert(root<=N && root>=1);
        for(int i=1;i<N;i++){
            scanf("%d%d",&x,&y);	
            assert(x>=1 && x<=N);
            assert(y>=1 && y<=N);
            assert(x!=y);
            myvector[x].push_back(y);
            myvector[y].push_back(x);
        }
        seg_size=0;
        parent[root]=root;
        depth[root]=0;
        dfs_pre(root);			//find heavy edges, parent, depth,which[]
        process(N);
        dfs_cal(root);			//construct segment tree;
        level=obtain(seg_size);
        for(int i=0;i<Q;i++){
            scanf(" %c",&c);
            if(c=='U'){
                scanf("%d%lld%lld",&x,&s,&k);
                assert(x>=1 && x<=N);
                assert(s>=1 && s<=1000000000);
                assert(k>=1 && k<=1000000000);
                A=fun(x,s,k);
                HL_Update(x,A);
                freq[x]= (freq[x] + A) % mod;
            }
            else{
                scanf("%d%d",&x,&y);
                assert(x>=1 && x<=N);
                assert(y>=1 && y<=N);
                anc=lca(x,y);
                A=HL_Query(x,anc);
                            B=HL_Query(y,anc);
                solution= part1(A,depth[x]) + part1 ( B, depth[y]) - freq[anc].v;
                if(anc!=root){
                    A = HL_Query(parent[anc],root);
                    solution = solution + part2(A,depth[anc],depth[x],depth[y]);
                }
                solution = solution % mod;
                if(solution<0)	solution+=mod;
                printf("%lld\n",solution);
            }
        }
    }
    int main()
    {
        constant();
        init();
        solve();
        return 0;
    }