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

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 →

Print in Reverse

Given a pointer to the head of a singly-linked list, print each data value from the reversed list. If the given list is empty, do not print anything. Example head* refers to the linked list with data values 1->2->3->Null Print the following: 3 2 1 Function Description: Complete the reversePrint function in the editor below. reversePrint has the following parameters: Sing

View Solution →

Reverse a linked list

Given the pointer to the head node of a linked list, change the next pointers of the nodes so that their order is reversed. The head pointer given may be null meaning that the initial list is empty. Example: head references the list 1->2->3->Null. Manipulate the next pointers of each node in place and return head, now referencing the head of the list 3->2->1->Null. Function Descriptio

View Solution →

Compare two linked lists

You’re given the pointer to the head nodes of two linked lists. Compare the data in the nodes of the linked lists to check if they are equal. If all data attributes are equal and the lists are the same length, return 1. Otherwise, return 0. Example: list1=1->2->3->Null list2=1->2->3->4->Null The two lists have equal data attributes for the first 3 nodes. list2 is longer, though, so the lis

View Solution →

Merge two sorted linked lists

This challenge is part of a tutorial track by MyCodeSchool Given pointers to the heads of two sorted linked lists, merge them into a single, sorted linked list. Either head pointer may be null meaning that the corresponding list is empty. Example headA refers to 1 -> 3 -> 7 -> NULL headB refers to 1 -> 2 -> NULL The new list is 1 -> 1 -> 2 -> 3 -> 7 -> NULL. Function Description C

View Solution →