Fibonacci Numbers Tree


Problem Statement :


Shashank loves trees and math. He has a rooted tree, T , consisting of N nodes uniquely labeled with integers in the inclusive range [1 , N ]. The node labeled as 1 is the root node of tree , and each node in  is associated with some positive integer value (all values are initially ).

Let's define Fk as the Kth  Fibonacci number. Shashank wants to perform 22 types of operations over his tree, T:

 1. UXK
Update the subtree rooted at node X such that the node at level 0 in subtree X (i.e., node X) will have  Fk added to it, all the nodes at level 1 will have Fk+1  added to them, and so on. More formally, all the nodes at a distance D  from node X  in the subtree of node  X will have the ( k - D)th Fibonacci number added to them.
 
2. QXY
Find the sum of all values associated with the nodes on the unique path from X  to  Y . Print your sum modulo  10^9 + 7 on a new line.
Given the configuration for tree T and a list of M  operations, perform all the operations efficiently.

Note: .F1 = F2 = 1.

Input Format

The first line contains 2  space-separated integers, N (the number of nodes in tree T) and M (the number of operations to be processed), respectively.
Each line i  of the N-1  subsequent lines contains an integer, P, denoting the parent of the ( i -1 )th node.
Each of the M subsequent lines contains one of the two types of operations mentioned in the Problem Statement above.

Constraints

1  <=  N, M  <=  10^5
1  <=  X,  Y  <=  N
1  <=  k  <=  10^15


Output Format

For each operation of type  2(i.e.,Q ), print the required answer modulo 10^9 + 7 on a new line.



Solution :



title-img


                            Solution in C :

In    C++  :







#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<cassert>
#define PB push_back
#define MP make_pair
#define sz(v) (in((v).size()))
#define forn(i,n) for(in i=0;i<(n);++i)
#define forv(i,v) forn(i,sz(v))
#define fors(i,s) for(auto i=(s).begin();i!=(s).end();++i)
#define all(v) (v).begin(),(v).end()
using namespace std;
typedef int in;
typedef vector<in> VI;
typedef vector<VI> VVI;
const in pmod=1000000007LL;
long long p2(long long a){
  return (1LL<<a);
}
template<typename T> T pw(T a, in b){
  T r=1LL;
  for(long long i=30;i>=0;i--){
    r*=r;
    if(b&p2(i))
      r*=a;
  }
  return r;
}
struct fp{
  long long a;
  fp(long long aa=0){
    a=aa;
    if(a<0 || a>=pmod){
      a%=pmod;
      if(a<0)
	a+=pmod;
    }
  }
  fp inv()const{
    return pw(*this,pmod-2);
  }
  fp operator*(const fp cp)const{
    return fp((a*cp.a)%pmod);
  }
  fp operator+(const fp cp)const{
    return fp((a+cp.a)>pmod?a+cp.a-pmod:a+cp.a);
  }
  fp operator/(const fp cp)const{
    return (*this)*cp.inv();
  }
  fp operator-(const fp cp)const{
    return (*this)+(-cp);
  }
  fp operator-()const{
    return (a==0?0:pmod-a);
  }
  fp& operator*=(const fp cp){
    return (*this)=(*this)*cp;
  }
  fp& operator/=(const fp cp){
    return (*this)=(*this)/cp;
  }
  fp& operator+=(const fp cp){
    return (*this)=(*this)+cp;
  }
  fp& operator-=(const fp cp){
    return (*this)=(*this)-cp;
  }
  bool operator==(const fp cp)const{
    return a==cp.a;
  }
  bool operator!=(const fp cp)const{
    return a!=cp.a;
  }
};
ostream& operator<<(ostream& os, fp a){
  return os<<a.a;
}
struct mat{
  vector<vector<fp> > a;
  in n,m;
  void ini(in pn, in pm){
    a.clear();
    n=pn;
    m=pm;
    a.resize(n,vector<fp>(m,fp(0LL)));
  }
  mat operator*(const mat& cp)const{
    assert(m==cp.n);
    mat r;
    r.ini(n,cp.m);
    long long t;
    forn(i,n){
      forn(j,cp.m){
	t=0;
	forn(k,m){
	  t+=a[i][k].a*cp.a[k][j].a;
	}
	r.a[i][j]=t;
      }
    }
    return r;
  }
  mat& operator*=(const mat& cp){
    assert(m==cp.n);
    mat r;
    r.ini(n,cp.m);
    long long t;
    forn(i,n){
      forn(j,cp.m){
	t=0;
	forn(k,m){
	  t+=a[i][k].a*cp.a[k][j].a;
	}
	r.a[i][j]=t;
      }
    }
    return *this=r;
  }
  mat operator+(const mat& cp)const{
    assert(n==cp.n && m==cp.m);
    mat r;
    r.ini(n,m);
    forn(i,n){
      forn(j,m){
	r.a[i][j]=a[i][j]+cp.a[i][j];
      }
    }
    return r;
  }
  mat& operator+=(const mat& cp){
    assert(n==cp.n && m==cp.m);
    forn(i,n){
      forn(j,m){
	a[i][j]+=cp.a[i][j];
      }
    }
    return *this;
  }
};
mat pwm(mat a, long long b){
  mat r=a;
  forv(i,r.a){
    forv(j,r.a[i])
      r.a[i][j]=(i==j);
  }
  bool odn=0;
  for(long long i=51;i>=0;i--){
    if(odn)
      r*=r;
    if(b&p2(i)){
      odn=1;
      r*=a;
    }
  }
  return r;
}
mat basfib;
mat fibmat;
mat ttp,ts;
mat smfib,sft;
vector<mat> smpw;
pair<fp,fp> fbat(long long a){
  ttp=pwm(fibmat,a-1)*basfib;
  return MP(ttp.a[0][0],ttp.a[1][0]);
}
struct fenw{
  vector<mat> fw;
  in n;
  void ini(in pn){
    n=pn;
    fw.clear();
    fw.resize(n);
    forn(i,n)
      fw[i].ini(3,1);
  }
  void ad(in l, mat ts){
    in ol=l;
    while(l<n){/*
		 mat tt=smpw[l-ol]*ts;
		 cout<<"ad "<<l<<endl;
		 forv(i,tt.a){
		 forv(j,tt.a[i]){
		 cout<<tt.a[i][j]<<" ";
		 }
		 cout<<endl;
		 }
		 cout<<endl;*/
      fw[l]+=smpw[l-ol]*ts;
      l|=(l+1);
    }
  }
  mat sm(in l){
    mat r;
    r.ini(3,1);
    in ol=l;
    while(l>=0){/*
		  mat tt=smpw[ol-l]*fw[l];
		  cout<<"sm "<<l<<endl;
		  forv(i,tt.a){
		  forv(j,tt.a[i]){
		  cout<<tt.a[i][j]<<" ";
		  }
		  cout<<endl;
		  }
		  cout<<endl;*/
      r+=smpw[ol-l]*fw[l];
      l&=(l+1);
      --l;
    }
    return r;
  }
};
vector<fenw> fws;
VI fid,floc;
VI sts;
const in mxp=18;
VI pr[mxp];
vector<fp> vlf,vls;
VI ht,pap;
void mkfid(in u, bool rq){
  if(fid[u]!=-2)
    return;
  if(sts[u]*2<sts[pr[0][u]] || u==0){
    if(rq==0){
      fid[u]=floc[u]=-1;
      return;
    }
    in s=sz(fws);
    fws.PB(fenw());
    fid[u]=s;
    floc[u]=0;
    return;
  }
  mkfid(pr[0][u],1);
  fid[u]=fid[pr[0][u]];
  floc[u]=floc[pr[0][u]]+1;
}
void proct(){
  in n=sz(pr[0]);
  sts.resize(n,1);
  fid=floc=VI(n,-2);
  for(in i=n-1;i>0;--i){
    sts[pr[0][i]]+=sts[i];
  }
  for(in i=n-1;i>=0;--i){
    mkfid(i,0);
  }
  for(in i=n-1;i>=0;--i){
    if(fid[i]<0)
      continue;
    if(sz(fws[fid[i]].fw))
      continue;
    fws[fid[i]].ini(floc[i]+1);
  }
  pap.resize(n);
  forn(i,n){
    if(i==0){
      pap[i]=-1;
      continue;
    }
    if(floc[i]==0 || floc[i]==-1){
      pap[i]=pr[0][i];
      continue;
    }
    pap[i]=pap[pr[0][i]];
  }
}
in lca(in u, in v){
  if(ht[u]<ht[v])
    swap(u,v);
  for(in i=mxp-1;i>=0;--i){
    if(ht[u]-p2(i)>=ht[v])
      u=pr[i][u];
  }
  assert(ht[u]==ht[v]);
  for(in i=mxp-1;i>=0;--i){
    if(pr[i][u]!=pr[i][v]){
      u=pr[i][u];
      v=pr[i][v];
    }
  }
  if(u!=v){
    u=pr[0][u];
    v=pr[0][v];
  }
  assert(u==v);
  return u;
}
struct qel{
  in u;
  qel(in a=0){
    u=a;
  }
  bool operator<(const qel& cp)const{
    return ht[u]<ht[cp.u];
  }
};
priority_queue<qel> q;
VI lvs,lad;
in vdt;
vector<mat> fv;
mat r;
vector<mat> ucm;
void clr(mat& c){
  forv(i,c.a){
    forv(j,c.a[i])
      c.a[i][j]=0;
  }
}
void prq(){
  qel tel;
  in tx;
  while(!q.empty()){
    tel=q.top();
    q.pop();
    tx=tel.u;
    if(lvs[tx]==vdt)
      continue;
    lvs[tx]=vdt;
    if(fid[tx]==-1){
      r+=ucm[tx]*fv[tx];
      if(tx==pr[0][tx]){
	clr(ucm[tx]);
	continue;
      }
      ucm[pr[0][tx]]+=smpw[1]*ucm[tx];
      clr(ucm[tx]);
      if(lad[pr[0][tx]]!=vdt){
	lad[pr[0][tx]]=vdt;
	q.push(qel(pr[0][tx]));
      }
      continue;
    }
    r+=ucm[tx]*fws[fid[tx]].sm(floc[tx]);
    if(pap[tx]==-1){
      clr(ucm[tx]);
      continue;
    }
    ucm[pap[tx]]+=smpw[floc[tx]+1]*ucm[tx];
    clr(ucm[tx]);
    if(lad[pap[tx]]!=vdt){
      lad[pap[tx]]=vdt;
      q.push(qel(pap[tx]));
    }
  }
}
void ansq(in tx, in ty){
  r.ini(3,1);
  mat cm;
  cm.ini(3,3);
  forn(i,3)
    cm.a[i][i]=1;
  in u=lca(tx,ty);
  q.push(qel(tx));
  q.push(qel(ty));
  q.push(qel(u));
  ucm[tx]+=cm;
  ucm[ty]+=cm;
  forn(i,3)
    cm.a[i][i]*=-1;
  ucm[u]+=cm;
  if(u!=0){
    q.push(qel(pr[0][u]));
    ucm[pr[0][u]]+=cm;
  }
  ++vdt;
  prq();
  cout<<r.a[0][0]<<"\n";
}
void adq(in tx, long long ty){
  mat crm;
  crm.ini(3,1);
  pair<fp,fp> tt=fbat(ty);
  crm.a[0][0]=crm.a[1][0]=tt.first;
  crm.a[2][0]=tt.second;
  if(fid[tx]==-1){
    fv[tx]+=crm;
    return;
  }
  fws[fid[tx]].ad(floc[tx],crm);
}
VI tpr;
VI cod,decod;
VVI tcd;
in nxdec;
void dfscod(in u){
  forv(i,tcd[u]){
    cod[nxdec]=tcd[u][i];
    decod[tcd[u][i]]=nxdec;
    ++nxdec;
    dfscod(tcd[u][i]);
  }
}
void mkcod(){
  in n=sz(tpr);
  cod=decod=VI(n,-1);
  tcd.resize(n);
  for(in i=1;i<n;++i)
    tcd[tpr[i]].PB(i);
  cod[0]=decod[0]=0;
  nxdec=1;
  dfscod(0);
}
void mkt(){
  in n,m;
  cin>>n>>m;
  lvs.resize(n,0);
  lad=lvs;
  vdt=1;
  ucm.resize(n);
  forn(i,n)
    ucm[i].ini(3,3);
  tpr.resize(n);
  tpr[0]=0;
  forn(i,n-1){
    cin>>tpr[i+1];
    --tpr[i+1];
  }
  mkcod();
  forn(z,mxp)
    pr[z].resize(n);
  ht.resize(n);
  fv.resize(n);
  forn(i,n)
    fv[i].ini(3,1);
  ht[0]=0;
  pr[0][0]=0;
  forn(i,n-1){
    pr[0][i+1]=decod[tpr[cod[i+1]]];
    assert(pr[0][i+1]<i+1);
    ht[i+1]=ht[pr[0][i+1]]+1;
  }
  for(in i=1;i<mxp;++i){
    forn(j,n)
      pr[i][j]=pr[i-1][pr[i-1][j]];
  }
  proct();
  char typ;
  in tx;
  long long ty;
  forn(zz,m){
    cin>>typ>>tx>>ty;
    if(typ=='Q'){
      ansq(decod[tx-1],decod[ty-1]);
    }
    else{
      adq(decod[tx-1],ty);
    }
  }
}
const in mx=100009;
int main(){
  ios::sync_with_stdio(0);
  cin.tie(0);
  smfib.ini(3,3);
  smfib.a[0][0]=smfib.a[0][2]=smfib.a[1][2]=smfib.a[2][1]=smfib.a[2][2]=1;
  sft.ini(3,1);
  basfib.ini(2,1);
  basfib.a[0][0]=basfib.a[1][0]=1LL;
  fibmat.ini(2,2);
  fibmat.a[0][0]=0;
  fibmat.a[0][1]=fibmat.a[1][0]=fibmat.a[1][1]=1LL;
  smpw.resize(mx);
  smpw[0].ini(3,3);
  forn(i,3)
    smpw[0].a[i][i]=1;
  for(in i=1;i<sz(smpw);++i)
    smpw[i]=smpw[i-1]*smfib;
  mkt();
  return 0;
}








In   Java  :








import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class H {
    InputStream is;
    PrintWriter out;
    String INPUT = "";
    
    void solve(){
        int n = ni();
        int Q = ni();
        par = new int[n];
        for(int i = 1;i < n;i++){
            par[i] = ni()-1;
        }
        par[0] = -1;
        int[][] g = parentToG(par);
        int[][] pars = parents3(g, 0);
        int[] ord = pars[1], dep = pars[2];
        clus = decomposeToHeavyLight(g,par, ord);
        cluspath = clusPaths(clus, ord);
        clusiind = clusIInd(cluspath, n);
        int m = cluspath.length;
        sts = new SegmentTreeMatrix[m];
        for(int i = 0;i < m;i++){
            sts[i] = new SegmentTreeMatrix(cluspath[i].length);
        }
        int[][] spar = logstepParents(par);
        
        for(int z = 0;z < Q;z++){
            char type = nc();
            if(type == 'U'){
                int x = ni()-1;
                long K = nl();
                sts[clus[x]].update(clusiind[x], K);
            }else{
                int mod = 1000000007;
                int x = ni()-1, y = ni()-1;
                int lca = lca2(x, y, spar, dep);
                long ret = d(x)+d(y)-d(lca)-d(par[lca]);
                ret %= mod;
                if(ret < 0)ret += mod;
                out.println(ret);
            }
        }
    }
    
    int[] par;
    int[] clus, clusiind;
    int[][] cluspath;
    SegmentTreeMatrix[] sts;
    
    long d(int x){
        if(x == -1)return 0;
        int[] lcx = new int[100];
        int[] lto = new int[100];
        int p = 0;
        int cx = clus[x];
        int ind = clusiind[x];
        while (true) {
            lcx[p] = cx;
            lto[p] = ind+1;
            p++;
            int con = par[cluspath[cx][0]];
            if(con == -1)break;
            ind = clusiind[con];
            cx = clus[con];
        }
        int[] v = {0, 0, 1, 0};
        for(int i = p-1;i >= 0;i--){
            v = sts[lcx[i]].apply(0, lto[i], v);
        }
        return v[3];
    }
    
    public static class SegmentTreeMatrix {
        public int M, H, N;
        public int[][][] node;
        public static int mod = 1000000007;
        public static long BIG = 8L*mod*mod;
        public static int S = 4;
        
        public SegmentTreeMatrix(int n){
            N = n;
            M = Integer.highestOneBit(Math.max(N-1, 1))<<2;
            H = M>>>1;
            
            node = new int[M][][];
            for(int i = 0;i < N;i++){
                node[H+i] = new int[S][S];
                node[H+i][0][0] = 1;
                node[H+i][0][1] = 1;
                node[H+i][1][0] = 1;
                node[H+i][3][1] = 1;
                node[H+i][2][2] = 1;
                node[H+i][3][3] = 1;
                node[H+i][3][0] = 1;
            }
            
            for(int i = H-1;i >= 1;i--)propagate(i);
        }
        
        private void propagate(int cur){
            node[cur] = prop2(node[2*cur], node[2*cur+1], node[cur]);
        }
        
        private int[][] prop2(int[][] L, int[][] R, int[][] C){
            if(L != null && R != null){
                C = mul(R, L, C, mod);
                return C;
            }else if(L != null){
                return prop1(L, C);
            }else if(R != null){
                return prop1(R, C);
            }else{
                return null;
            }
        }
        
        private int[][] prop1(int[][] L, int[][] C){
            if(C == null){
                C = new int[S][];
                for(int i = 0;i < S;i++){
                    C[i] = Arrays.copyOf(L[i], S);
                }
            }else{
                for(int i = 0;i < S;i++){
                    C[i] = Arrays.copyOf(L[i], S);
                }
            }
            return C;
        }
        
        public void update(int pos, long x) {
            int[][] M = {{1, 1}, {1, 0}};
            int[] v = {1, 0};
            v = pow(M, v, x-1);
            node[H+pos][0][2] += v[0];
            if(node[H+pos][0][2] >= mod)node[H+pos][0][2] -= mod;
            node[H+pos][1][2] += v[1];
            if(node[H+pos][1][2] >= mod)node[H+pos][1][2] -= mod;
            node[H+pos][3][2] += v[0];
            if(node[H+pos][3][2] >= mod)node[H+pos][3][2] -= mod;
            for(int i = H+pos>>>1;i >= 1;i>>>=1)propagate(i);
        }
        
        public int[] apply(int l, int r, int[] v){
            return apply(l, r, 0, H, 1, v);
        }
        
                   if(l <= cl && cr <= r){
                return mul(node[cur], v, mod);
            }else{
                int mid = cl+cr>>>1;
                if(cl < r && l < mid){
                    v = apply(l, r, cl, mid, 2*cur, v);
                }
                if(mid < r && l < cr){
                    v = apply(l, r, mid, cr, 2*cur+1, v);
                }
                return v;
            }
        }
        
        
        public static int[] mul(int[][] A, int[] v, int mod){
            int m = A.length;
            int n = v.length;
            int[] w = new int[m];
            for(int i = 0;i < m;i++){
                long sum = 0;
                for(int k = 0;k < n;k++){
                    sum += (long)A[i][k] * v[k];
                    if(sum >= BIG)sum -= BIG;
                }
                w[i] = (int)(sum % mod);
            }
            return w;
        }
        
        public static int[][] 
mul(int[][] A, int[][] B, int[][] C, int mod){
            int m = A.length;
            int n = A[0].length;
            int o = B[0].length;
            if(C == null)C = new int[m][o];
            for(int i = 0;i < m;i++){
                for(int j = 0;j < o;j++){
                    long sum = 0;
                    for(int k = 0;k < n;k++){
                        sum += (long)A[i][k] * B[k][j];
                        if(sum >= BIG)sum -= BIG;
                    }
                    sum %= mod;
                    C[i][j] = (int)sum;
                }
            }
            return C;
        }
        
        public static int[] pow(int[][] A, int[] v, long e){
            for(int i = 0;i < v.length;i++){
                if(v[i] >= mod)v[i] %= mod;
            }
            int[][] MUL = A;
            for(;e > 0;e>>>=1) {
                if((e&1)==1)v = mul(MUL, v);
                MUL = p2(MUL);
            }
            return v;
        }
        
        public static int[] mul(int[][] A, int[] v){
            int m = A.length;
            int n = v.length;
            int[] w = new int[m];
            for(int i = 0;i < m;i++){
                long sum = 0;
                for(int k = 0;k < n;k++){
                    sum += (long)A[i][k] * v[k];
                    if(sum >= BIG)sum -= BIG;
                }
                w[i] = (int)(sum % mod);
            }
            return w;
        }
        
        public static int[][] p2(int[][] A){
            int n = A.length;
            int[][] C = new int[n][n];
            for(int i = 0;i < n;i++){
                long[] sum = new long[n];
                for(int k = 0;k < n;k++){
                    for(int j = 0;j < n;j++){
                        sum[j] += (long)A[i][k] * A[k][j];
                        if(sum[j] >= BIG)sum[j] -= BIG;
                    }
                }
                for(int j = 0;j < n;j++){
                    C[i][j] = (int)(sum[j] % mod);
                }
            }
            return C;
        }

    }    
    
public static int lca2(int a, int b, 
int[][] spar, int[] depth) {
        if (depth[a] < depth[b]) {
  b = ancestor(b, depth[b] - depth[a], spar);
        } else if (depth[a] > depth[b]) {
 a = ancestor(a, depth[a] - depth[b], spar);
        }

        if (a == b)
            return a;
        int sa = a, sb = b;
for (int low = 0, high = depth[a],
 t = Integer.highestOneBit(high), 
k = Integer.numberOfTrailingZeros(t); t > 0;
 t >>>= 1, k--) {
            if ((low ^ high) >= t) {
                if (spar[k][sa] != spar[k][sb]) {
                    low |= t;
                    sa = spar[k][sa];
                    sb = spar[k][sb];
                } else {
                    high = low | t - 1;
                }
            }
        }
        return spar[0][sa];
    }

protected static int ancestor(int a, int m, int[][] spar) {
     for (int i = 0; m > 0 && a != -1; m >>>= 1, i++) {
            if ((m & 1) == 1)
                a = spar[i][a];
        }
        return a;
    }

    public static int[][] logstepParents(int[] par) {
        int n = par.length;
 int m = Integer.numberOfTrailingZeros(
Integer.highestOneBit(n - 1)) + 1;
        int[][] pars = new int[m][n];
        pars[0] = par;
        for (int j = 1; j < m; j++) {
            for (int i = 0; i < n; i++) {
                pars[j][i] = pars[j - 1][i] == -1 ? -1
                        : pars[j - 1][pars[j - 1][i]];
            }
        }
        return pars;
    }

    
    public static int[] 
decomposeToHeavyLight(int[][] g, int[] par, int[] ord) {
        int n = g.length;
        int[] size = new int[n];
        Arrays.fill(size, 1);
        for (int i = n - 1; i > 0; i--)
            size[par[ord[i]]] += size[ord[i]];

        int[] clus = new int[n];
        Arrays.fill(clus, -1);
        int p = 0;
        outer: for (int i = 0; i < n; i++) {
            int u = ord[i];
            if (clus[u] == -1)
                clus[u] = p++;
            for (int v : g[u]) {
                if (par[u] != v && size[v] >= size[u] / 2) {
                    clus[v] = clus[u];
                    continue outer;
                }
            }
            for (int v : g[u]) {
                if (par[u] != v) {
                    clus[v] = clus[u];
                    break;
                }
            }
        }
        return clus;
    }

 public static int[][] clusPaths(int[] clus, int[] ord) {
        int n = clus.length;
        int[] rp = new int[n];
        int sup = 0;
        for (int i = 0; i < n; i++) {
            rp[clus[i]]++;
            sup = Math.max(sup, clus[i]);
        }
        sup++;

        int[][] row = new int[sup][];
        for (int i = 0; i < sup; i++)
            row[i] = new int[rp[i]];

        for (int i = n - 1; i >= 0; i--) {
            row[clus[ord[i]]][--rp[clus[ord[i]]]] = ord[i];
        }
        return row;
    }

    public static int[] clusIInd(int[][] clusPath, int n) {
        int[] iind = new int[n];
        for (int[] path : clusPath) {
            for (int i = 0; i < path.length; i++) {
                iind[path[i]] = i;
            }
        }
        return iind;
    }
    
    public static int[][] parentToG(int[] par){
        int n = par.length;
        int[] ct = new int[n];
        for(int i = 0;i < n;i++){
            if(par[i] >= 0){
                ct[i]++;
                ct[par[i]]++;
            }
        }
        int[][] g = new int[n][];
        for(int i = 0;i < n;i++){
            g[i] = new int[ct[i]];
        }
        for(int i = 0;i < n;i++){
            if(par[i] >= 0){
                g[par[i]][--ct[par[i]]] = i;
                g[i][--ct[i]] = par[i];
            }
        }
        return g;
    }


    public static int[][] parents3(int[][] g, int root) {
        int n = g.length;
        int[] par = new int[n];
        Arrays.fill(par, -1);

        int[] depth = new int[n];
        depth[0] = 0;

        int[] q = new int[n];
        q[0] = root;
        for (int p = 0, r = 1; p < r; p++) {
            int cur = q[p];
            for (int nex : g[cur]) {
                if (par[cur] != nex) {
                    q[r++] = nex;
                    par[nex] = cur;
                    depth[nex] = depth[cur] + 1;
                }
            }
        }
        return new int[][] { par, q, depth };
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }
    
    void run() throws Exception{
        is = INPUT.isEmpty() ? 
System.in : new ByteArrayInputStream(INPUT.getBytes());
        out = new PrintWriter(System.out);
        
        long s = System.currentTimeMillis();
        solve();
        out.flush();
 if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");
    }

 public static void main(String[] args) 
throws Exception { new H().run(); }
    
    private byte[] inbuf = new byte[1024];
    private int lenbuf = 0, ptrbuf = 0;
    
    private int readByte(){
if(lenbuf == -1)throw new InputMismatchException();
        if(ptrbuf >= lenbuf){
            ptrbuf = 0;
            try { lenbuf = is.read(inbuf); }
 catch (IOException e) 
{ throw new InputMismatchException(); }
            if(lenbuf <= 0)return -1;
        }
        return inbuf[ptrbuf++];
    }
    
    private boolean isSpaceChar(int c)
 { return !(c >= 33 && c <= 126); }
    private int skip() 
{ int b; while((b = readByte()) != -1
 && isSpaceChar(b)); return b; }
    
    private double nd() 
{ return Double.parseDouble(ns()); }
    private char nc() { return (char)skip(); }
    
    private String ns(){
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!(isSpaceChar(b))){
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    
    private char[] ns(int n){
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while(p < n && !(isSpaceChar(b))){
            buf[p++] = (char)b;
            b = readByte();
        }
   return n == p ? buf : Arrays.copyOf(buf, p);
    }
    
    private char[][] nm(int n, int m){
        char[][] map = new char[n][];
        for(int i = 0;i < n;i++)map[i] = ns(m);
        return map;
    }
    
    private int[] na(int n){
        int[] a = new int[n];
        for(int i = 0;i < n;i++)a[i] = ni();
        return a;
    }
    
    private int ni(){
        int num = 0, b;
        boolean minus = false;
        while((b = readByte()) != -1 
&& !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }
        
        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    
    private long nl(){
        long num = 0;
        int b;
        boolean minus = false;
while((b = readByte()) != -1 
&& !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }
        
        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    
    private static void tr(Object... o)
 { System.out.println(Arrays.deepToString(o)); }
}








In   Python3  :




#!/usr/bin/python

mod = 10**9 + 7

cache = { 0: (0, 1), 1: (1, 1) }
def fib_pair(n):
    if n in cache:
        return cache[n]

    hn = n//2
    f, fp = fib_pair(hn)
    if n&1:
        res = (fp*fp + f*f) % mod, (2*f+fp)*fp % mod
    else:
        fm = fp - f
        if fm < 0:
            fm += mod
        res = (2*fm+f)*f % mod, (fp*fp + f*f) % mod

    if n < 1000000:
        cache[n] = res

    return res

n, m = map(int, input().strip().split())
parents = (n+1) * [0]
children = [[] for _ in range(n+1)]
for i in range(2, n+1):
    j = int(input())
    parents[i] = j
    children[j].append(i)
depths = (n+1) * [0]
stack = [(1, 1)]
while stack:
    i, d = stack.pop()
    depths[i] = d
    for j in children[i]:
        stack.append((j, d+1))

nrs = (n+1) * [0]
for _ in range(m):
    q, si, sj = input().strip().split()
    if q == 'U':
        x, k = int(si), int(sj)
        fibs = list(fib_pair(k))
        stack = [(x, 0)]
        while stack:
            y, l = stack.pop()
            if l >= len(fibs):
                fibs.append((fibs[-1] + fibs[-2]) % mod)
            nrs[y] += fibs[l]
            for z in children[y]:
                stack.append((z, l+1))
    else:
        i, j = int(si), int(sj)
        if depths[i] < depths[j]:
            i, j = j, i
        fsum = 0
        while depths[j] < depths[i]:
            fsum += nrs[i]
            i = parents[i]
        while i != j:
            fsum += nrs[i] + nrs[j]
            j = parents[j]
            i = parents[i]
        fsum += nrs[i]
        print(fsum % mod)
                        








View More Similar Problems

Unique Colors

You are given an unrooted tree of n nodes numbered from 1 to n . Each node i has a color, ci. Let d( i , j ) be the number of different colors in the path between node i and node j. For each node i, calculate the value of sum, defined as follows: Your task is to print the value of sumi for each node 1 <= i <= n. Input Format The first line contains a single integer, n, denoti

View Solution →

Fibonacci Numbers Tree

Shashank loves trees and math. He has a rooted tree, T , consisting of N nodes uniquely labeled with integers in the inclusive range [1 , N ]. The node labeled as 1 is the root node of tree , and each node in is associated with some positive integer value (all values are initially ). Let's define Fk as the Kth Fibonacci number. Shashank wants to perform 22 types of operations over his tree, T

View Solution →

Pair Sums

Given an array, we define its value to be the value obtained by following these instructions: Write down all pairs of numbers from this array. Compute the product of each pair. Find the sum of all the products. For example, for a given array, for a given array [7,2 ,-1 ,2 ] Note that ( 7 , 2 ) is listed twice, one for each occurrence of 2. Given an array of integers, find the largest v

View Solution →

Lazy White Falcon

White Falcon just solved the data structure problem below using heavy-light decomposition. Can you help her find a new solution that doesn't require implementing any fancy techniques? There are 2 types of query operations that can be performed on a tree: 1 u x: Assign x as the value of node u. 2 u v: Print the sum of the node values in the unique path from node u to node v. Given a tree wi

View Solution →

Ticket to Ride

Simon received the board game Ticket to Ride as a birthday present. After playing it with his friends, he decides to come up with a strategy for the game. There are n cities on the map and n - 1 road plans. Each road plan consists of the following: Two cities which can be directly connected by a road. The length of the proposed road. The entire road plan is designed in such a way that if o

View Solution →

Heavy Light White Falcon

Our lazy white falcon finally decided to learn heavy-light decomposition. Her teacher gave an assignment for her to practice this new technique. Please help her by solving this problem. You are given a tree with N nodes and each node's value is initially 0. The problem asks you to operate the following two types of queries: "1 u x" assign x to the value of the node . "2 u v" print the maxim

View Solution →