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

Array Manipulation

Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in the array. Example: n=10 queries=[[1,5,3], [4,8,7], [6,9,1]] Queries are interpreted as follows: a b k 1 5 3 4 8 7 6 9 1 Add the valu

View Solution →

Print the Elements of a Linked List

This is an to practice traversing a linked list. Given a pointer to the head node of a linked list, print each node's data element, one per line. If the head pointer is null (indicating the list is empty), there is nothing to print. Function Description: Complete the printLinkedList function in the editor below. printLinkedList has the following parameter(s): 1.SinglyLinkedListNode

View Solution →

Insert a Node at the Tail of a Linked List

You are given the pointer to the head node of a linked list and an integer to add to the list. Create a new node with the given integer. Insert this node at the tail of the linked list and return the head node of the linked list formed after inserting this new node. The given head pointer may be null, meaning that the initial list is empty. Input Format: You have to complete the SinglyLink

View Solution →

Insert a Node at the head of a Linked List

Given a pointer to the head of a linked list, insert a new node before the head. The next value in the new node should point to head and the data value should be replaced with a given value. Return a reference to the new head of the list. The head pointer given may be null meaning that the initial list is empty. Function Description: Complete the function insertNodeAtHead in the editor below

View Solution →

Insert a node at a specific position in a linked list

Given the pointer to the head node of a linked list and an integer to insert at a certain position, create a new node with the given integer as its data attribute, insert this node at the desired position and return the head node. A position of 0 indicates head, a position of 1 indicates one node away from the head and so on. The head pointer given may be null meaning that the initial list is e

View Solution →

Delete a Node

Delete the node at a given position in a linked list and return a reference to the head node. The head is at position 0. The list may be empty after you delete the node. In that case, return a null value. Example: list=0->1->2->3 position=2 After removing the node at position 2, list'= 0->1->-3. Function Description: Complete the deleteNode function in the editor below. deleteNo

View Solution →