Fury's Network
Difficulty: Hard

**S.H.I.E.L.D** is an espionage and law-enforcement agency headed by Colonel Nick Fury. Over the years, HYDRA secretly infiltrated **S.H.I.E.L.D** and used the agency to their advantage in many ways. They recruited a large sum of all the agents and silently killed off anyone who got in their way. Soon, Nick Fury found out that **S.H.I.E.L.D** was compromised.<br/><br/> 
So, he decided to share highly confidential information among the other loyal members through a secret network. The network has **N** systems (numbered from **1 to N**) and there exists a unique communication pathway between any two systems in the network. The communication link between two adjacent systems has some cost **D**. Colonel Fury performs some covert operations in the network. For each operation, he chooses two systems from the network and then increase/decrease or replace the costs of all the links in the communication pathway between the chosen systems.<br/><br/>
Agent Romanoff is worried about the utilities of the different pathways. The utility of a communication pathway is the sum of the cubes of the costs of all the links in the pathway.  She keeps pinging Colonel Fury to determine the utility between two systems at any time. Fury, being the creator of this network, tells her about the utility instantaneously.<br/><br/>
Now, the question that arises is how covert is the network actually? Can only Fury answer for the utilities or can you also?

###Input:
The first line of the input contains the integer **N**, denoting the number of systems.<br/>
The next **N-1** lines contain triples of the form **X Y D** with the meaning that there is a link between the **X-th** and the **Y-th** system having cost **D**.<br/>
The next line contains a single integer **M**, denoting the number of queries.<br/>
The next **M** lines contains queries in one of the following forms:<br/>
**Q X Y:**  utility between the systems **X** and **Y**.<br/>
**I X Y Z:** Add **Z** to the cost of all the links between the systems **X** and **Y**<br/>
**R X Y Z:** Replace the cost of each link with **Z** between systems **X** and **Y**.

###Output:
For every query of type **Q**, print the utility on a separate line. It is assured that the answer will fit in long long int.

###Constraints
1<=**N, M**<=100000<br/>
1<=**X, Y**<=**N**<br/>
1<=**D**<=1000<br/>
-1000<=**Z**<=1000<br/>

###Example
**Input:**<br/>
5<br/>
1 2 1<br/>
2 3 2<br/>
1 4 3<br/>
4 5 4<br/>
10<br/>
Q 1 3<br/>
Q 2 4<br/>
I 1 5 1<br/>
Q 1 5<br/>
R 3 4 4<br/>
Q 3 4<br/>
Q 2 5<br/>
I 3 5 -1<br/>
Q 3 5<br/>
Q 4 1<br/><br/>

**Output**<br/>
9<br/>
28<br/>
189<br/>
192<br/>
253<br/>
145<br/>
27







Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:


Reference solution (C++):
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #define MAX 100001
    #define DMAX 262145
    using namespace std;
    struct node
    {
        int sum,u;
        long long sqsum;
        long long cubsum;
        bool ch,rep;
    }seg[DMAX];

    struct rx
    {
        int s;
        long long sq;
        long long cu;
    }res[MAX];

    struct vertex
    {
        int to,cost;
    }e;

    vector<vertex> v[MAX];
    int arr[MAX],l[MAX],p[MAX][17],sub[MAX],pos[MAX],chainHead[MAX],chainInd[MAX];
    int indx,z,logn,qs,qe,qn,chainNo,ptr=1;
    bool cht;
    void build_tree(int i,int j,int ind)
    {
        seg[ind].u=0;
        seg[ind].ch=false;
        seg[ind].rep=false;
        if(i==j)
        {
            seg[ind].sum=arr[i];
            seg[ind].sqsum=arr[i]*arr[i];
            seg[ind].cubsum=seg[ind].sqsum*arr[i];
            return;
        }
        int mid,l,r;
        mid=(i+j)>>1;
        l=ind<<1;
        r=l+1;
        build_tree(i,mid,l);
        build_tree(mid+1,j,r);
        seg[ind].sum=seg[l].sum+seg[r].sum;
        seg[ind].sqsum=seg[l].sqsum+seg[r].sqsum;
        seg[ind].cubsum=seg[l].cubsum+seg[r].cubsum;
    }

    int update(int i,int j,int ind)
    {
        if(j<qs || i>qe)
            return 0;
        int mid,l,r;
        mid=(i+j)>>1;
        l=ind<<1;
        r=l+1;
        if(seg[ind].ch)
        {
            if(seg[ind].rep)
            {
               seg[ind].cubsum=0;
               seg[ind].sqsum=0;
               seg[ind].sum=0;
               if(i!=j)
               {
                   seg[l].u=0;
                   seg[r].u=0;
               }
            }
            if(i!=j)
            {
                seg[l].u+=seg[ind].u;
                seg[l].ch=true;
                seg[l].rep=seg[ind].rep|seg[l].rep;
                seg[r].u+=seg[ind].u;
                seg[r].ch=true;
                seg[r].rep=seg[ind].rep|seg[r].rep;
            }
            int u=seg[ind].u;
            seg[ind].cubsum+=(long long)(j-i+1)*u*u*u+(seg[ind].sqsum+seg[ind].sum*u)*3*u;
            seg[ind].sqsum+=(long long)(j-i+1)*u*u+seg[ind].sum*2*u;
            seg[ind].sum+=(j-i+1)*u;
            seg[ind].ch=false;
            seg[ind].rep=false;
            seg[ind].u=0;
        }
        if(i>=qs && j<=qe)
        {
            int diff=j-i+1;
            if(!qn)
            {
                seg[ind].u=0;
                seg[ind].rep=true;
                res[indx].s=diff*z-seg[ind].sum;
                res[indx].sq=(long long)diff*z*z-seg[ind].sqsum;
                res[indx].cu=(long long)diff*z*z*z - seg[ind].cubsum;
            }
            else
            {
                res[indx].s=diff*z;
                res[indx].sq=(long long)diff*z*z+2*z*seg[ind].sum;
                res[indx].cu=(long long)diff*z*z*z + (seg[ind].sqsum+seg[ind].sum*z)*3*z;
            }
            seg[ind].u+=z;
            seg[ind].ch=true;
            return indx++;
        }
        int left,right;
        left=update(i,mid,l);
        right=update(mid+1,j,r);
        if(!left)
        {
            seg[ind].sum+=res[right].s;
            seg[ind].sqsum+=res[right].sq;
            seg[ind].cubsum+=res[right].cu;
            return right;
        }
        if(!right)
        {
            seg[ind].sum+=res[left].s;
            seg[ind].sqsum+=res[left].sq;
            seg[ind].cubsum+=res[left].cu;
            return left;
        }
        res[left].s+=res[right].s;
        res[left].sq+=res[right].sq;
        res[left].cu+=res[right].cu;
        seg[ind].sum+=res[left].s;
        seg[ind].sqsum+=res[left].sq;
        seg[ind].cubsum+=res[left].cu;
        return left;
    }
    long long query(int i,int j,int ind)
    {
        if(j<qs || i>qe)
            return 0;
        int mid,l,r;
        mid=(i+j)>>1;
        l=ind<<1;
        r=l+1;
        if(seg[ind].ch)
        {
            if(seg[ind].rep)
            {
               seg[ind].sqsum=0;
               seg[ind].sum=0;
               seg[ind].cubsum=0;
               if(i!=j)
               {
                   seg[l].u=0;
                   seg[r].u=0;
               }
            }
            if(i!=j)
            {
                seg[l].u+=seg[ind].u;
                seg[l].ch=true;
                seg[l].rep=seg[ind].rep|seg[l].rep;
                seg[r].u+=seg[ind].u;
                seg[r].ch=true;
                seg[r].rep=seg[ind].rep|seg[r].rep;
            }
            int u=seg[ind].u;
            seg[ind].cubsum+=(long long)(j-i+1)*u*u*u+(seg[ind].sqsum+seg[ind].sum*u)*3*u;
            seg[ind].sqsum+=(long long)(j-i+1)*u*u+seg[ind].sum*2*u;
            seg[ind].sum+=(j-i+1)*u;
            seg[ind].ch=false;
            seg[ind].rep=false;
            seg[ind].u=0;

        }
        if(i>=qs&&j<=qe)
            return seg[ind].cubsum;
        return query(i,mid,l)+query(mid+1,j,r);
    }


    long long query_up(int i,int j)
    {
        if(i==j)
          return 0;
        int ichain=chainInd[i],jchain=chainInd[j];
        long long ans=0;
        while(ichain!=jchain)
        {
            qs=pos[chainHead[ichain]];
            qe=pos[i];
            ans+=query(1,ptr,1);
            i=p[chainHead[ichain]][0];
            ichain=chainInd[i];
        }
        if(i!=j)
        {
            qs=pos[j]+1;
            qe=pos[i];
            ans+=query(1,ptr,1);
        }
        return ans;
    }
    void update_up(int i,int j)
    {
        if(i==j)
            return;
        int ichain=chainInd[i],jchain=chainInd[j];
        while(ichain!=jchain)
        {
            qs=pos[chainHead[ichain]];
            qe=pos[i];
            update(1,ptr,1);
            i=p[chainHead[ichain]][0];
            ichain=chainInd[i];
        }
        if(i!=j)
        {
            qs=pos[j]+1;
            qe=pos[i];
            update(1,ptr,1);
        }
    }
    void HLD(int s,int cost,int pre)
    {
        if(!chainHead[chainNo])
            chainHead[chainNo]=s;
        pos[s]=ptr;
        arr[ptr++]=cost;
        chainInd[s]=chainNo;
        int i,c,x,ind=0;

        for(i=0;i<v[s].size();i++)
        {
            x=v[s][i].to;
            if(x!=pre)
            {
                if(sub[x]>sub[ind])
                    {
                        ind=x;
                        c=v[s][i].cost;
                    }
            }
        }
        if(ind)
            HLD(ind,c,s);

        for(i=0;i<v[s].size();i++)
        {
            x=v[s][i].to;
            if(x!=pre && x!=ind)
            {
                chainNo++;
                HLD(x,v[s][i].cost,s);
            }
        }
    }
    void dfs(int s,int pre)
    {
        int i,x;
        p[s][0]=pre;
        l[s]=l[pre]+1;
        sub[s]=1;
        for(i=0;i<v[s].size();i++)
        {
            x=v[s][i].to;
            if(x!=pre)
            {
                dfs(x,s);
                sub[s]+=sub[x];
            }
        }
    }
    int LCA(int a,int b)
    {
        int i,lg;
        if(l[a]<l[b])
            swap(a,b);
        for(lg=0;(1<<lg)<=l[a];lg++);
        lg--;
        if(l[a]!=l[b])
        {
            for(i=lg;i>=0;i--)
                if(l[a]-(1<<i)>=l[b])
                    a=p[a][i];
        }
        if(a==b)
            return a;
        for(i=lg;i>=0;i--)
        {
            if(p[a][i] && p[a][i]!=p[b][i])
            {
                a=p[a][i];
                b=p[b][i];
            }
        }
        return p[a][0];

    }
    long long q(int i,int j)
    {
        int lca=LCA(i,j);
        return query_up(i,lca)+query_up(j,lca);

    }
    void upd(int i,int j)
    {
        int lca=LCA(i,j);
        update_up(i,lca);
        update_up(j,lca);

    }
    int main()
    {
        int i,j,n,m,x,y;
        char ch[2];
        int turn=20;
        scanf("%d",&n);
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&e.cost);
            e.to=y;
            v[x].push_back(e);
            e.to=x;
            v[y].push_back(e);
        }
        l[0]=-1;
        dfs(1,0);
        for(logn=0;(1<<logn)<=n;logn++);
        /*DP for LCA*/
        for(j=1;j<logn;j++)
        for(i=1;i<=n;i++)
        {
            x=p[p[i][j-1]][j-1];
            if(x)
                p[i][j]=x;
        }
        HLD(1,-1,0);
        ptr--;
        build_tree(1,ptr,1);
        scanf("%d",&m);
        while(m--)
        {
            indx=1;
            scanf("%s",ch);
            scanf("%d%d",&i,&j);
            if(*ch=='Q')
            {
                printf("%lld\n",q(i,j));
            }
            else
            {
                scanf("%d",&z);
                if(*ch=='I')
                    qn=1;
                else
                    qn=0;
                upd(i,j);
            }

        }
        return 0;
    }