Recalling Early Days GP with Trees
Difficulty: Hard

[Chinese Version](https://hr-testcases.s3.amazonaws.com/959/959-chinese.md)<br/>
[Russian Version](https://hr-testcases.s3.amazonaws.com/959/959_rus.md)<br/>

You are given a [tree](http://en.wikipedia.org/wiki/Tree_(graph_theory)) with N nodes and each has a value associated with it. You are given Q queries, each of which is either an update or a retrieval operation. 

The **update query** is of the format

	i j X

This means you'd have to add a [GP](http://en.wikipedia.org/wiki/Geometric_progression) series to the nodes which lie in the path from node `i` to node `j` (both inclusive) with first term of the GP as `X` on node `i` and the common ratio as `R` (given in the input)

The **retrieval** query is of the format

i j

You need to return the sum of the node values (S) lying in the path from node i to node j modulo 100711433. 

**Input Format**  
The first line contains two integers (N and R respectively) separated by a space.  
In the next N-1 lines, the i<sup>th</sup> line describes the i<sup>th</sup> edge: a line with two integers a b separated by a single space denotes an edge between a, b.  
The next line contains 2 space separated integers (U and Q respectively) representing the number of Update and Query operations to follow.  
U lines follow. Each of the next U lines contains 3 space separated integers (i,j, and X respectively).  
Each of the next Q lines contains 2 space separated integers, i and j respectively. 

**Output Format**  
It contains exactly Q lines and each line containing the answer of the i<sup>th</sup> query.

**Constraints**

2 <= N <= 100000  
2 <= R <= 10<sup>9</sup>  
1 <= U <= 100000  
1 <= Q <= 100000  
1 <= X <= 10  
1 <= a, b, i, j <= N  

**Sample Input**  

	6 2
    1 2
    1 4
    2 6
    4 5
    4 3
    2 2
    1 6 3
    5 3 5
    6 4
    5 1

**Sample Output**

	31
    18

**Explanation**

The node values after the first updation becomes :  

    3 6 0 0 0 12  
    
The node values after second updation becomes :  

    3 6 20 10 5 12  
    
Answer to Query #1: 12 + 6 + 3 + 10 = 31  
Answer to Query #2: 5 + 10 +3 = 18  

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:

Editorial: Recalling Early Days with GP Trees : 101 Hack January Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><a href="https://www.hackerrank.com/contests/101jan14/challenges/recalling-early-days-gp-with-trees">Recalling Early Days with GP Trees</a></p>

<p><strong>Difficulty Level</strong> : Medium-Hard <br>
<strong>Problem Setter</strong> : <a href="https://www.hackerrank.com/devuy11">Devendra Agarwal</a> <br>
<strong>Problem Tester</strong> : <a href="https://www.hackerrank.com/wanbo">Wanbo</a>  </p>

<p><strong>Approach</strong> </p>

<p><strong>Observations</strong></p>

<ol>
<li><p>The Number 100711433 is a prime number , so that we can find its inverse (except when R  is not a multiple of 100711433)</p></li>
<li><p>You need to first tackle all the Updates and then all the Queries.</p></li>
</ol>

<p>Choose any node as root of the tree.</p>

<p>Make 2 arrays  Dist_DFSL[] and Dist_DFSR[] for the Tree.</p>

<p><strong>Update Method</strong></p>

<p>i j St</p>

<p>Let anc be the ancestor node of node i and node j.</p>

<p>Add value St in Dist_DFSL[i]</p>

<p>Add -St*power(R,d1+1) in Dist_DFSL[Parent[anc]] where d1 denotes the total number of edges between node i and node anc and power(a,b) denotes a^b mod 100711433</p>

<p>Add -St*power(R,d1) in Dist_DFSR[anc]  where d1 denotes the total number of edges between node i and node anc and power(a,b) denotes a^b mod 100711433</p>

<p>Add St*power(R,d1+d2) in Dist_DFSR[j] where d2 represent the total edges in path from ancestor to j.</p>

<p>d1 and d2 can be calculated by precalculating the depth of each node from root.</p>

<p>d1=depth[i]-depth[anc]</p>

<p>d2=depth[j]-depth[anc]</p>

<p>After all Update Queries, we need the final values at each node and to do so ,we run a DFS on the Tree and do the following:</p>

<p>Dist_DFSL[parent]=(Dist_DFSL[parent]+Dist_DFSL[child]*R)%mod</p>

<p>Dist_DFSR[parent]=(Dist_DFSR[parent]+Dist_DFSR[child]*R_inverse)%mod</p>

<p><strong>Note</strong> :: R_Inverse * R = 1 mod (100711433)</p>

<p>Now value at each Node is :</p>

<p>Sum[Node]=Dist_DFSL[Node]+ Dist_DFSR[NOde]</p>

<p>Now, Run a BFS(or DFS) on the graph and store the sum to each Node from the root in Sum[] array.</p>

<p><strong>Answering the Query</strong></p>

<p>i j</p>

<p>Answer= Sum[i] + Sum[j] - Sum[anc] - Sum[Parent[anc]]</p>

<p><strong>NOTE</strong>:Precaution in Calculating R_inv and solving the problem when R is multiple of 100711433</p>

<p><strong>Time Complexity: O( (U+Q) log N)</strong> //computing lca part otherwise everything in O(1) time.</p>

<p><strong>Setter's Solution</strong>  </p>

<pre><code>//Author : Devendra Agarwal
#include&lt;stdio.h&gt;
#include&lt;algorithm&gt;
#include&lt;iostream&gt;
#include&lt;vector&gt;
#include&lt;string.h&gt;
using namespace std;

#define MaxN 100001     //Maximum Nodes

typedef long long int ll;

int N,R,level[MaxN],Parent[MaxN],Dist_DFSL[MaxN],Dist_DFSR[MaxN],Root[MaxN][17],Store_Power_R[MaxN],store[MaxN],mod=100711433,R_inv,Sum[MaxN],Queue[MaxN];

vector&lt;int&gt; Graph[MaxN];    //to store graph


/* To calculate the inverse of a number in multiplicative modulo b*/
int inverse(int a,int b) //b&gt;a
{
    int Remainder,p0=0,p1=1,pcurr=1,q,m=b;
    while(a!=0)
    {
        Remainder=b%a;
        q=b/a;
        if(Remainder!=0)
        {
            pcurr=p0-((ll)p1*(ll)q)%m;
            if(pcurr&lt;0)
                pcurr+=m;
            p0=p1;
            p1=pcurr;
        }
        b=a;
        a=Remainder;
    }
    return pcurr;
}

/*Storing the Parent and height using DFS*/
void DFS(int root)
{
    for(vector&lt;int&gt; ::iterator it=Graph[root].begin();it!=Graph[root].end();it++){
        if((*it)!=Parent[root]){    //not visiting more than once
            level[(*it)]=level[root]+1;
            Parent[(*it)]=root;
            DFS((*it));
        }
    }
    return;
}
/*Calculating Data necessary for calculating ancestor and some pre-processing for quicker implementation*/
void process()
{
    memset(Root,-1,sizeof(Root));
    for(int i=1;i&lt;=N;i++)   Root[i][0]=Parent[i];
    for(int i=1;(1&lt;&lt;i) &lt;= N; i++)
        for(int j=1;j&lt;=N;j++)
            if(Root[j][i-1]!=-1)
                Root[j][i]=Root[Root[j][i-1]][i-1];

    store[0]=0;
    store[1]=0;
    int cmp=2;
    for(int i=2;i&lt;=N;i++){
        if(cmp&gt;i)   store[i]=store[i-1];
        else{
            store[i]=store[i-1]+1;
            cmp&lt;&lt;=1;
        }
    }
    Store_Power_R[0]=1;
    for(int i=1;i&lt;=N;i++)
        Store_Power_R[i]=((ll)Store_Power_R[i-1]*(ll)R)%mod;
}
/*Returns the lca of two nodes, same implementation as was used in topcoder tutorials*/
int lca(int p,int q)        //Fnds the LCA of 2 nodes
{
    int temp;

    if(level[p]&gt;level[q]){
        temp=p;p=q;q=temp;
    }

    //level[q]&gt;=level[p]
    int steps=store[level[q]];
    for(int i=steps;i&gt;=0;i--)
        if(level[q]-(1&lt;&lt;i) &gt;= level[p])
            q=Root[q][i];

    if(p==q)    return p;
    for(int i=steps;i&gt;=0;i--)
        if(Root[p][i]!=Root[q][i])
            p=Root[p][i],q=Root[q][i];
    return Parent[p];
}
/*This Find the Dist_DFSL and Dist_DFSR after all update queries*/
void DFS_new(int root)
{
    for(vector&lt;int&gt; ::iterator it=Graph[root].begin();it!=Graph[root].end();it++){
        if((*it)!=Parent[root]){        //not visiting more than once
            DFS_new((*it));
            Dist_DFSL[root]=(Dist_DFSL[root]+((ll)Dist_DFSL[*it]*(ll)R)%mod)%mod;       //Updating root from children
            Dist_DFSR[root]=(Dist_DFSR[root]+((ll)Dist_DFSR[*it]*(ll)R_inv)%mod)%mod;       //Updating root from children
        }
    }       
}
/*This find the Sum[] array*/
void BFS(int root)
{
    Queue[0]=root;
    int st=0,end=1,node;
    while(st&lt;end){
        node=Queue[st];
        st++;
        for(vector&lt;int&gt;::iterator it=Graph[node].begin();it!=Graph[node].end();it++){
            if((*it)!=Parent[node]){
                Sum[(*it)]=(Sum[(*it)]+Sum[node])%mod;
                Queue[end]=(*it);
                end++;
            }
        }
    }
}
int main()
{
    int x,y,U,Q,anc,ans,St;
    scanf("%d%d",&amp;N,&amp;R);
    if(R%mod!=0)        //Checking the tricky case
        R_inv=inverse(R,mod);
    else
        R_inv=0;

    for(int i=1;i&lt;N;i++){
        scanf("%d%d",&amp;x,&amp;y);
        Graph[x].push_back(y);
        Graph[y].push_back(x);
    }

    level[1]=0;
    Parent[1]=0;
    DFS(1);
    process();

    memset(Dist_DFSL,0,sizeof(Dist_DFSL));
    memset(Dist_DFSR,0,sizeof(Dist_DFSR));
    memset(Sum,0,sizeof(Sum));

    scanf("%d%d",&amp;U,&amp;Q);
    while(U--){
        scanf("%d%d%d",&amp;x,&amp;y,&amp;St);
        anc=lca(x,y);
        Dist_DFSL[x]=(Dist_DFSL[x]+St)%mod;
        Dist_DFSL[Parent[anc]]=(Dist_DFSL[Parent[anc]]-((ll)St*(ll)Store_Power_R[level[x]-level[anc]+1])%mod)%mod;
        Dist_DFSR[y]=(Dist_DFSR[y]+((ll)St*(ll)Store_Power_R[level[y]+level[x]-2*level[anc]])%mod)%mod;
        Dist_DFSR[anc]=(Dist_DFSR[anc]-((ll)St*(ll)Store_Power_R[level[x]-level[anc]])%mod)%mod;
    }

    Dist_DFSL[0]=Dist_DFSR[0]=0;

    DFS_new(1);

    if(R%mod!=0)            //Check for the tricky test case
        for(int i=1;i&lt;=N;i++)   Sum[i]=(Dist_DFSL[i]+Dist_DFSR[i])%mod;
    else
        for(int i=1;i&lt;=N;i++)   Sum[i]=Dist_DFSL[i];

    BFS(1);

    while(Q--){
        scanf("%d%d",&amp;x,&amp;y);
        anc=lca(x,y);
        ans=(Sum[x]+Sum[y]-Sum[anc]-Sum[Parent[anc]])%mod;
        printf("%d\n",(ans+ mod)%mod);
    }

    return 0;
}
</code></pre>

<p><strong>Tester's Solution</strong>  </p>

<pre><code>#include &lt;map&gt;
#include &lt;set&gt;
#include &lt;list&gt;
#include &lt;queue&gt;
#include &lt;deque&gt;
#include &lt;stack&gt;
#include &lt;bitset&gt;
#include &lt;vector&gt;
#include &lt;ctime&gt;
#include &lt;cmath&gt;
#include &lt;cstdio&gt;
#include &lt;string&gt;
#include &lt;cstring&gt;
#include &lt;cassert&gt;
#include &lt;numeric&gt;
#include &lt;iomanip&gt;
#include &lt;sstream&gt;
#include &lt;fstream&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;
typedef long long       LL;
typedef pair&lt;int, int&gt;  PII;
typedef pair&lt;LL, LL&gt;    PLL;
typedef vector&lt;int&gt;     VI;
typedef vector&lt;LL&gt;      VL;
typedef vector&lt;PII&gt;     VPII;
typedef vector&lt;PLL&gt;     VPLL;
#define MM(a,x) memset(a,x,sizeof(a));
#define ALL(x)  (x).begin(), (x).end()
#define P(x)    cerr&lt;&lt;"["#x&lt;&lt;" = "&lt;&lt;(x)&lt;&lt;"]\n"
#define PP(x,i) cerr&lt;&lt;"["#x&lt;&lt;i&lt;&lt;" = "&lt;&lt;x[i]&lt;&lt;"]\n"
#define P2(x,y) cerr&lt;&lt;"["#x" = "&lt;&lt;(x)&lt;&lt;", "#y" = "&lt;&lt;(y)&lt;&lt;"]\n"
#define TM(a,b) cerr&lt;&lt;"["#a" -&gt; "#b": "&lt;&lt;1e3*(b-a)/CLOCKS_PER_SEC&lt;&lt;"ms]\n";
#define FOR(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define rep(i, n) for(int i = 0; i &lt; n; i++)
#define UN(v) sort(ALL(v)), v.resize(unique(ALL(v))-v.begin())
#define mp make_pair
#define pb push_back
#define x first
#define y second
struct _ {_() {ios_base::sync_with_stdio(0);}} _;
template&lt;class T&gt; void PV(T a, T b) {while(a != b)cout &lt;&lt; *a++, cout &lt;&lt; (a != b ? " " : "\n");}
template&lt;class T&gt; inline bool chmin(T &amp;a, T b) {return a &gt; b ? a = b, 1 : 0;}
template&lt;class T&gt; inline bool chmax(T &amp;a, T b) {return a &lt; b ? a = b, 1 : 0;}
template&lt;class T&gt; string tostring(T x, int len = 0) {stringstream ss; ss &lt;&lt; x; string r = ss.str(); if(r.length() &lt; len) r = string(len - r.length(), '0') + r; return r;}
template&lt;class T&gt; void convert(string x, T&amp; r) {stringstream ss(x); ss &gt;&gt; r;}
template&lt;class A, class B&gt; ostream&amp; operator&lt;&lt;(ostream &amp;o, pair&lt;A, B&gt; t) {o &lt;&lt; "(" &lt;&lt; t.x &lt;&lt; ", " &lt;&lt; t.y &lt;&lt; ")"; return o;}
const int inf = 0x3f3f3f3f;
const int mod = 100711433;
const int N = 111111;

const int V = 111111;
vector&lt;int&gt; g[V];
vector&lt;int&gt; chain[V];
int father[V], heavy[V];
int depth[V], size[V];
int chainID[V], top[V];
int tL[V], tR[V];
int w[V];

void DFS(int u) {
    size[u] = 1;
    for(int i = 0; i &lt; g[u].size(); i++) {
        int v = g[u][i];
        if(v == father[u]) continue;
        father[v] = u;
        depth[v] = depth[u] + 1;
        DFS(v);
        size[u] += size[v];
        if(heavy[u] == -1 || size[v] &gt; size[heavy[u]]) heavy[u] = v;
    }
}

void HLD_DFS(int n) {
    MM(heavy, -1);
    MM(father, -1);
    MM(depth, 0);
    DFS(0);
    int id = 0;
    for(int i = 0; i &lt; n; i++) {
        if(father[i] == -1 || heavy[father[i]] != i) {
            for(int k = i; k != -1; k = heavy[k]) {
                chainID[k] = id;
                chain[id].push_back(k);
                top[k] = i;
            }
            id++;
        }
    }

    for(int i = 0; i &lt; id; i++) {
        tL[i] = i &gt; 0 ? tR[i - 1] + 1 : 1;
        tR[i] = tL[i] + chain[i].size() - 1;
        for(int j = 0; j &lt; chain[i].size(); j++) {
            w[chain[i][j]] = tL[i] + j;
        }
    }
}

int LCA(int u, int v) {
    while(chainID[u] != chainID[v]) {
        if(depth[top[u]] &gt; depth[top[v]]) swap(u, v);
        v = father[top[v]];
    }
    return depth[u] &lt; depth[v] ? u : v;
}


LL exp(LL x, LL n, LL m = ~0ULL &gt;&gt; 1) {
    x %= m;
    LL r = 1 % m;
    while(n) {
        if(n &amp; 1) r = r * x % m;
        x = x * x % m, n &gt;&gt;= 1;
    }
    return r;
}

LL inv(int x) {
    return exp(x, mod - 2, mod);
}

int n, R;
int iR;
LL q[N];
LL iq[N];

void ADD(int u, int v, int s, int r) {
    /*
    if(depth[u] &gt; depth[v]) {
        int ns;
        while(chain[u] != chain[v]) {
            int len = top[u] - u + 1;
            ns = s * q[top[u] - u + 1] % mod;
            add(w[top[u]], w[u], ns * R % mod, iR);
            u = top[u] + 1;
        }
        add(w[v], w[u], ns * R % mod , iR);
    } else {
        int ns;
        swap(u, v);
        VPII vp;
        while(chain[u] != chain[v]) {
            int len = top[u] - u + 1;
            ns = s * q[top[u] - u + 1] % mod;
            vp.pb(mp(top[u], w[u]));
            u = top[u] + 1;
        }
        add(w[v], w[u], ns * R % mod , iR);
    }
    */
}

LL d[N];

int main() {
    cin &gt;&gt; n &gt;&gt; R;
    for(int i = 0; i &lt; n - 1; i++) {
        int u, v;
        cin &gt;&gt; u &gt;&gt; v;
        u--, v--;
        g[u].pb(v);
        g[v].pb(u);
    }

    HLD_DFS(n);

    int U, Q;
    cin &gt;&gt; U &gt;&gt; Q;

    iR = inv(R);
    iq[0] = q[0] = 1;
    for(int i = 1; i &lt; N; i++) q[i] = q[i - 1] * R % mod;
    for(int i = 1; i &lt; N; i++) iq[i] = iq[i - 1] * iR % mod;

    while(U--) {
        int u, v, s;
        cin &gt;&gt; u &gt;&gt; v &gt;&gt; s;
        u--, v--;
        int x = LCA(u, v);
        int t = depth[u] - depth[x];
        vector&lt;int&gt; left, right;
        while(u != x) {
            left.pb(u);
            u = father[u];
        }
        left.pb(x);
        while(v != x) {
            right.pb(v);
            v = father[v];
        }
        reverse(ALL(right));
        for(int i = 0; i &lt; right.size(); i++) left.pb(right[i]);

        for(int i = 0; i &lt; left.size(); i++) {
            d[left[i]] += s;
            s = (LL) s * R % mod;
        }
        /*      ADD(u, x, s, R);
                ADD(x, v, s * q[t] % mod, R);
                ADD(x, x, -s * q[t] % mod, 1);*/
    }

    while(Q--) {
        int u, v;
        cin &gt;&gt; u &gt;&gt; v;
        u--, v--;
        int x = LCA(u, v);
//      LL r = SUM(u) + SUM(v) - 2 * SUM(father[x]);
//      r = (r % mod + mod) % mod;
        LL r = 0;
        while(u != x) {
            r += d[u];
            u = father[u];
        }
        r += d[x];
        while(v != x) {
            r += d[v];
            v = father[v];
        }
        r = (r % mod + mod) % mod;
        cout &lt;&lt; r &lt;&lt; endl;
    }
    return 0;
}
</code></pre>

Reference solution (C++):

    #include <map>
    #include <set>
    #include <list>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <bitset>
    #include <vector>
    #include <ctime>
    #include <cmath>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <cassert>
    #include <numeric>
    #include <iomanip>
    #include <sstream>
    #include <fstream>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long       LL;
    typedef pair<int, int>  PII;
    typedef pair<LL, LL>    PLL;
    typedef vector<int>     VI;
    typedef vector<LL>      VL;
    typedef vector<PII>     VPII;
    typedef vector<PLL>     VPLL;
    #define MM(a,x) memset(a,x,sizeof(a));
    #define ALL(x)  (x).begin(), (x).end()
    #define P(x)	cerr<<"["#x<<" = "<<(x)<<"]\n"
    #define PP(x,i)	cerr<<"["#x<<i<<" = "<<x[i]<<"]\n"
    #define P2(x,y)	cerr<<"["#x" = "<<(x)<<", "#y" = "<<(y)<<"]\n"
    #define TM(a,b)	cerr<<"["#a" -> "#b": "<<1e3*(b-a)/CLOCKS_PER_SEC<<"ms]\n";
    #define FOR(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
    #define rep(i, n) for(int i = 0; i < n; i++)
    #define UN(v) sort(ALL(v)), v.resize(unique(ALL(v))-v.begin())
    #define mp make_pair
    #define pb push_back
    #define x first
    #define y second
    struct _ {_() {ios_base::sync_with_stdio(0);}} _;
    template<class T> void PV(T a, T b) {while(a != b)cout << *a++, cout << (a != b ? " " : "\n");}
    template<class T> inline bool chmin(T &a, T b) {return a > b ? a = b, 1 : 0;}
    template<class T> inline bool chmax(T &a, T b) {return a < b ? a = b, 1 : 0;}
    template<class T> string tostring(T x, int len = 0) {stringstream ss; ss << x; string r = ss.str(); if(r.length() < len) r = string(len - r.length(), '0') + r; return r;}
    template<class T> void convert(string x, T& r) {stringstream ss(x); ss >> r;}
    template<class A, class B> ostream& operator<<(ostream &o, pair<A, B> t) {o << "(" << t.x << ", " << t.y << ")"; return o;}
    const int inf = 0x3f3f3f3f;
    const int mod = 100711433;
    const int N = 111111;
    
    const int V = 111111;
    vector<int> g[V];
    vector<int> chain[V];
    int father[V], heavy[V];
    int depth[V], size[V];
    int chainID[V], top[V];
    int tL[V], tR[V];
    int w[V];
    
    void DFS(int u) {
    	size[u] = 1;
    	for(int i = 0; i < g[u].size(); i++) {
    		int v = g[u][i];
    		if(v == father[u]) continue;
    		father[v] = u;
    		depth[v] = depth[u] + 1;
    		DFS(v);
    		size[u] += size[v];
    		if(heavy[u] == -1 || size[v] > size[heavy[u]]) heavy[u] = v;
    	}
    }
    
    void HLD_DFS(int n) {
    	MM(heavy, -1);
    	MM(father, -1);
    	MM(depth, 0);
    	DFS(0);
    	int id = 0;
    	for(int i = 0; i < n; i++) {
    		if(father[i] == -1 || heavy[father[i]] != i) {
    			for(int k = i; k != -1; k = heavy[k]) {
    				chainID[k] = id;
    				chain[id].push_back(k);
    				top[k] = i;
    			}
    			id++;
    		}
    	}
    
    	for(int i = 0; i < id; i++) {
    		tL[i] = i > 0 ? tR[i - 1] + 1 : 1;
    		tR[i] = tL[i] + chain[i].size() - 1;
    		for(int j = 0; j < chain[i].size(); j++) {
    			w[chain[i][j]] = tL[i] + j;
    		}
    	}
    }
    
    int LCA(int u, int v) {
    	while(chainID[u] != chainID[v]) {
    		if(depth[top[u]] > depth[top[v]]) swap(u, v);
    		v = father[top[v]];
    	}
    	return depth[u] < depth[v] ? u : v;
    }
    
    
    LL exp(LL x, LL n, LL m = ~0ULL >> 1) {
    	x %= m;
    	LL r = 1 % m;
    	while(n) {
    		if(n & 1) r = r * x % m;
    		x = x * x % m, n >>= 1;
    	}
    	return r;
    }
    
    LL inv(int x) {
    	return exp(x, mod - 2, mod);
    }
    
    int n, R;
    int iR;
    LL q[N];
    LL iq[N];
    
    void ADD(int u, int v, int s, int r) {
    	/*
    	if(depth[u] > depth[v]) {
    		int ns;
    		while(chain[u] != chain[v]) {
    			int len = top[u] - u + 1;
    			ns = s * q[top[u] - u + 1] % mod;
    			add(w[top[u]], w[u], ns * R % mod, iR);
    			u = top[u] + 1;
    		}
    		add(w[v], w[u], ns * R % mod , iR);
    	} else {
    		int ns;
    		swap(u, v);
    		VPII vp;
    		while(chain[u] != chain[v]) {
    			int len = top[u] - u + 1;
    			ns = s * q[top[u] - u + 1] % mod;
    			vp.pb(mp(top[u], w[u]));
    			u = top[u] + 1;
    		}
    		add(w[v], w[u], ns * R % mod , iR);
    	}
    	*/
    }
    
    LL d[N];
    
    int main() {
    	cin >> n >> R;
    	for(int i = 0; i < n - 1; i++) {
    		int u, v;
    		cin >> u >> v;
    		u--, v--;
    		g[u].pb(v);
    		g[v].pb(u);
    	}
    
    	HLD_DFS(n);
    
    	int U, Q;
    	cin >> U >> Q;
    
    	iR = inv(R);
    	iq[0] = q[0] = 1;
    	for(int i = 1; i < N; i++) q[i] = q[i - 1] * R % mod;
    	for(int i = 1; i < N; i++) iq[i] = iq[i - 1] * iR % mod;
    
    	while(U--) {
    		int u, v, s;
    		cin >> u >> v >> s;
    		u--, v--;
    		int x = LCA(u, v);
    		int t = depth[u] - depth[x];
    		vector<int> left, right;
    		while(u != x) {
    			left.pb(u);
    			u = father[u];
    		}
    		left.pb(x);
    		while(v != x) {
    			right.pb(v);
    			v = father[v];
    		}
    		reverse(ALL(right));
    		for(int i = 0; i < right.size(); i++) left.pb(right[i]);
    
    		for(int i = 0; i < left.size(); i++) {
    			d[left[i]] += s;
    			s = (LL) s * R % mod;
    		}
    		/*		ADD(u, x, s, R);
    				ADD(x, v, s * q[t] % mod, R);
    				ADD(x, x, -s * q[t] % mod, 1);*/
    	}
    
    	while(Q--) {
    		int u, v;
    		cin >> u >> v;
    		u--, v--;
    		int x = LCA(u, v);
    //		LL r = SUM(u) + SUM(v) - 2 * SUM(father[x]);
    //		r = (r % mod + mod) % mod;
    		LL r = 0;
    		while(u != x) {
    			r += d[u];
    			u = father[u];
    		}
    		r += d[x];
    		while(v != x) {
    			r += d[v];
    			v = father[v];
    		}
    		r = (r % mod + mod) % mod;
    		cout << r << endl;
    	}
    	return 0;
    }