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

Poisonous Plants

There are a number of plants in a garden. Each of the plants has been treated with some amount of pesticide. After each day, if any plant has more pesticide than the plant on its left, being weaker than the left one, it dies. You are given the initial values of the pesticide in each of the plants. Determine the number of days after which no plant dies, i.e. the time after which there is no plan

View Solution →

AND xor OR

Given an array of distinct elements. Let and be the smallest and the next smallest element in the interval where . . where , are the bitwise operators , and respectively. Your task is to find the maximum possible value of . Input Format First line contains integer N. Second line contains N integers, representing elements of the array A[] . Output Format Print the value

View Solution →

Waiter

You are a waiter at a party. There is a pile of numbered plates. Create an empty answers array. At each iteration, i, remove each plate from the top of the stack in order. Determine if the number on the plate is evenly divisible ith the prime number. If it is, stack it in pile Bi. Otherwise, stack it in stack Ai. Store the values Bi in from top to bottom in answers. In the next iteration, do the

View Solution →

Queue using Two Stacks

A queue is an abstract data type that maintains the order in which elements were added to it, allowing the oldest elements to be removed from the front and new elements to be added to the rear. This is called a First-In-First-Out (FIFO) data structure because the first element added to the queue (i.e., the one that has been waiting the longest) is always the first one to be removed. A basic que

View Solution →

Castle on the Grid

You are given a square grid with some cells open (.) and some blocked (X). Your playing piece can move along any row or column until it reaches the edge of the grid or a blocked cell. Given a grid, a start and a goal, determine the minmum number of moves to get to the goal. Function Description Complete the minimumMoves function in the editor. minimumMoves has the following parameter(s):

View Solution →

Down to Zero II

You are given Q queries. Each query consists of a single number N. You can perform any of the 2 operations N on in each move: 1: If we take 2 integers a and b where , N = a * b , then we can change N = max( a, b ) 2: Decrease the value of N by 1. Determine the minimum number of moves required to reduce the value of N to 0. Input Format The first line contains the integer Q.

View Solution →