#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
#define ll long long
#define INF 1000000000
#define p(x) ('0'<=x&&x<='9')
char cc; int C;
template <class T>
void read( T &x )
{
x=0; cc=getchar(); C=1;
while(!p(cc)) { if(cc=='-') C=-1; cc=getchar(); }
while(p(cc)) { x=x*10+cc-48; cc=getchar(); }
x*=C;
}
using namespace std;
#define N 150010
#define Q 200010
int TO[N<<1],val[N<<1],NXT[N<<1],fst[N],e_tot;
void add_e(int _,int __,int ___)
{
TO[e_tot]=__; val[e_tot]=___; NXT[e_tot]=fst[_]; fst[_]=e_tot++;
TO[e_tot]=_; val[e_tot]=___; NXT[e_tot]=fst[__]; fst[__]=e_tot++;
}
int age[N];
//
struct sav
{
ll tot; int age;
sav(int _,int __) : tot(_),age(__){}
bool operator < (const sav &x) const { return age<x.age; }
};
struct rec
{
int fa,id;
int son[3],_tot;
vector <sav> Arr[3];
vector <sav> dist;
int operator [] (const int &x) { return son[x]; }
}pool[N];
int root,siz[N],mxsiz[N],d[N],T,now;
bool use[N];
void dfs_push(int x,int f,ll dist)
{
pool[now].dist.push_back(sav(dist,x));
siz[x]=1;
pool[now].Arr[pool[now]._tot].push_back(sav(dist,age[x]));
for(int i=fst[x];~i;i=NXT[i])
{
if(use[TO[i]]||TO[i]==f) continue;
dfs_push(TO[i],x,dist+val[i]);
siz[x]+=siz[TO[i]];
}
}
void getroot(int x,int f)
{
siz[x]=1; mxsiz[x]=0;
for(int i=fst[x];~i;i=NXT[i])
{
if(TO[i]==f||use[TO[i]]) continue;
getroot(TO[i],x);
siz[x]+=siz[TO[i]];
mxsiz[x]=max(mxsiz[x],siz[TO[i]]);
}
mxsiz[x]=max(mxsiz[x],T-siz[x]);
if(mxsiz[x]<mxsiz[root]) root=x;
}
void dfs_build(int x,int f)
{
now=x;
pool[x].fa=f;
use[x]=true;
for(int i=fst[x];~i;i=NXT[i])
{
if(use[TO[i]]) continue;
root=0;
T=siz[TO[i]];
dfs_push(TO[i],0,val[i]);
getroot(TO[i],0);
pool[now].son[pool[now]._tot]=root;
siz[root]=siz[TO[i]];
sort(pool[now].Arr[pool[now]._tot].begin(),pool[now].Arr[pool[now]._tot].end());
for(int j=1;j<pool[now].Arr[pool[now]._tot].size();j++)
pool[now].Arr[pool[now]._tot][j].tot+=pool[now].Arr[pool[now]._tot][j-1].tot;
pool[now]._tot++;
}
pool[now].dist.push_back(sav(0,now));
sort(pool[now].dist.begin(),pool[now].dist.end());
for(int i=0;i<pool[x]._tot;i++) dfs_build(pool[x][i],x);
}
int n,m,A;
void pre()
{
int _,__,___;
read(n); read(m); read(A);
for(int i=1;i<=n;i++)
{
fst[i]=-1;
read(age[i]);
age[i]++;
}
for(int i=1;i<n;i++)
{
read(_); read(__); read(___);
add_e(_,__,___);
}
T=n;
mxsiz[0]=INF;
getroot(1,0);
dfs_build(root,0);
}
ll get_ans(int x,int l,int r)
{
sav _(0,l-1),__(0,r);
vector <sav> :: iterator it,it2;
int L,R,pre=0,tot=0,___,S=x;
ll dist=0,ret=0;
while(x)
{
tot=0;
for(int i=0;i<pool[x]._tot;i++)
{
if(pool[x][i]==pre)
continue;
it = upper_bound(pool[x].Arr[i].begin(),pool[x].Arr[i].end(),_);
if(it!=pool[x].Arr[i].begin())
{
it--;
ret-=it->tot;
it++;
}
it2 = upper_bound(pool[x].Arr[i].begin(),pool[x].Arr[i].end(),__);
if(it2!=pool[x].Arr[i].begin())
{
it2--;
ret+=it2->tot;
it2++;
}
tot+=distance(it,it2);
}
if(age[x]<=r&&age[x]>=l) tot++;
it=lower_bound(pool[x].dist.begin(),pool[x].dist.end(),sav(0,S));
dist=it->tot;
ret+=dist*tot;
pre=x;
x=pool[x].fa;
}
return ret;
}
ll lastans;
int main()
{
// freopen("BZOJ4012.in","r",stdin);
ll _,__,___,L,R;
pre();
while(m--)
{
read(_); read(__); read(___);
__+=lastans; ___+=lastans;
__%=A; ___%=A;
__++; ___++;
L=min(__,___);
R=max(__,___);
lastans=get_ans(_,L,R);
printf("%lld\n",lastans);
}
return 0;
}