Description

风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群。

很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 个地方,编号为 ,被 条带权的边连接起来。每个地方都住着一个妖怪,其中第 个地方的妖怪年龄是 。妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 。妖怪和人一样,兴趣点随着年龄的变化自然就会变化,比如我们的 岁少女幽香和八云紫就比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以幽香打算选择一个地方 为编号),然后在 开一家面向年龄在 之间(即年龄大于等于 、小于等于 )的妖怪的店。也有可能 这个地方离这些妖怪比较远,于是幽香就想要知道所有年龄在 之间的妖怪,到点 的距离的和是多少(妖怪到 的距离是该妖怪所在地方到 的路径上的边的权之和) ,幽香把这个称为这个开店方案的方便值。

幽香她们还没有决定要把店开在哪里,八云紫倒是准备了很多方案,于是幽香想要知道,对于每个方案,方便值是多少呢。

Input

第一行三个用空格分开的数 ,表示树的大小、开店的方案个数和妖怪的年龄上限。

第二行 个用空格分开的数 表示第 个地点妖怪的年龄,满足 。(年龄是可以为 的,例如刚出生的妖怪的年龄为

接下来 行,每行三个用空格分开的数 ,表示树上的顶点 之间有一条权为 )的边, 是顶点编号。

接下来 行,每行三个用空格分开的数 。对于这 行的每一行,用 计算出 ,表示询问“在地方 开店,面向妖怪的年龄区间为 的方案的方便值是多少”。对于其中第 行, 的计算方法为:。对于第 到第 行,假设前一行得到的方便值为 ,那么当前行的 计算方法为:

Output

对于每个方案,输出一行表示方便值。

Sample Input

10 10 10 
0 0 7 2 1 4 7 7 7 9  
1 2 270 
2 3 217 
1 4 326 
2 5 361 
4 6 116 
3 7 38 
1 8 800 
6 9 210 
7 10 278 
8 9 8 
2 8 0 
9 3 1 
8 0 8 
4 2 7 
9 7 3 
4 7 0 
2 2 7 
3 2 1 
2 3 4

Sample Output

1603 
957 
7161 
9466 
3232 
5223 
1879 
1669 
1282 
0

HINT

对于所有数据,

Solution

主席树

xjb维护一波。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<bitset>
#define mk make_pair
#define fi first
#define se second
#define pii pair<ll,ll>
#define pb push_back
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
inline ll read() {ll x = 0; char ch = getchar(), w = 1;while(ch < '0' || ch > '9') {if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * w;}
void write(ll x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');}
inline void writeln(ll x) {write(x);puts("");} 
const int N = 2e5 + 66;
int n, m, A;
int v[N];
struct Edge {
    int u, v, nxt, w;
}e[N * 2];
int head[N], en;
void addedge(int x, int y, int z) {
    e[++en].u = x, e[en].v = y, e[en].nxt = head[x], head[x] = en, e[en].w = z;
} 
ll d[N];
int siz[N], son[N],fa[N], idw[N];
ll w[N];
void dfs1(int x, int F) {
    siz[x] = 1;
    fa[x] = F;
    for(int i = head[x]; i;i = e[i].nxt) {
        int y = e[i].v;
        if(y == F) continue;
    //    printf("%d->%d\n", x, y);
        d[y] = d[x] + e[i].w;
        idw[y] = e[i].w;
        dfs1(y, x);
        siz[x] += siz[y];
        if(siz[son[x]] < siz[y]) son[x] = y;
    }
}
int top[N], num, id[N];
void dfs2(int x, int F) {
//    printf("x=%d\n", x);
    id[x] = ++num;
    w[id[x]] = idw[x];
    top[x] = F;
    if(!son[x]) return;
    dfs2(son[x], F);
    for(int i = head[x]; i;i = e[i].nxt) {
        int y = e[i].v;
        if(y == son[x] || y == fa[x]) continue;
    //    printf("%d->%d\n", x, y);
        dfs2(y, y);
    }
}
int b[N], tot, r[N];
ll sum[N];
bool cmp(int x, int y) {
    return v[x] < v[y];
}
int rt[N];
ll cnt[N];


struct T {
    struct Tree {
        int l, r;
        ll s; 
        int tag;
    }t[N * 35];
    int tot;
    void ins(int pre, int &o, int l, int r, int ql, int qr) {
        o = ++tot;
        t[o] = t[pre];
        if(ql <= l && qr >= r) {
            //t[o].s += w[r] - w[l - 1];
            ++t[o].tag;
            return;
        }
        t[o].s += max(0ll, w[min(qr, r)] - w[max(l, ql) - 1]);
        int mid = (l + r) >> 1;
        if(ql <= mid) ins(t[pre].l, t[o].l, l, mid, ql, qr);
        if(qr > mid) ins(t[pre].r, t[o].r, mid + 1, r, ql, qr);
        //t[o].s = t[t[o].l].s + t[t[o].r].s;
        //t[o].s += w[min(qr, r)] - w[max(l, ql) - 1];
    } 
    ll query(int o, int l, int r, int ql, int qr,ll stag) {
        if(!o) return 0;
        ll res = (w[min(qr, r)] - w[max(l, ql) - 1]) * t[o].tag;
        if(ql <= l && qr >= r) {
            return t[o].s + res;
        }
        stag += t[o].tag;
        int mid = (l + r) >> 1;
        if(qr <= mid) return res + query(t[o].l, l, mid, ql, qr, stag);
        if(ql > mid) return res + query(t[o].r, mid + 1, r, ql, qr, stag);
        return res + query(t[o].l, l, mid, ql, qr, stag) + query(t[o].r, mid +1, r, ql, qr, stag);
    }
}t;

void update(int &jd, int x) {
    while(x) {
        t.ins(jd, jd, 1, n, id[top[x]], id[x]);
        x = fa[top[x]];
    }
}
ll query(int pre, int o, int x) {
    ll res = 0;
    while(x) {
        res += t.query(o, 1, n, id[top[x]], id[x], 0);
        res -= t.query(pre, 1, n, id[top[x]], id[x], 0);
        x = fa[top[x]];
    }
    return res;
}
ll solve(int u, int l, int r) {
    ll ans = (cnt[r] - cnt[l - 1]) * d[u] + sum[r] - sum[l - 1];
//    printf("sum1=%lld,sum2=%lld,sum3=%lld\n", (cnt[r] - cnt[l - 1]) * d[u], sum[r] - sum[l - 1], query(rt[l - 1], rt[r], u));    
    return ans - 2 * query(rt[l - 1], rt[r], u );
}
int main() {
//    freopen("a.in","r",stdin);
    n = read(), m = read(), A = read();
    for(int i = 1; i <= n; ++i) b[++tot] = v[i] = read();
    for(int i = 1; i < n; ++i) {
        int x = read(), y = read(), z = read();
        addedge(x, y, z);
        addedge(y, x, z);
    }
    dfs1(1, 0);
    dfs2(1, 1);
    b[++tot] = -1;
    sort(b +1, b +1 +tot);
    tot = unique(b +1, b +1 + tot) - b - 1;
    for(int i = 1; i <= n; ++i) v[i] = lower_bound(b +1, b +1 +tot, v[i]) - b;
    for(int i = 1; i <= n; ++i) sum[v[i]] += d[i], w[i] += w[i - 1], ++cnt[v[i]];
    for(int i = 1; i <= tot; ++i) sum[i] += sum[i - 1], cnt[i] += cnt[i - 1];
    for(int i = 1; i <= n; ++i) r[i] = i;
    sort(r +1, r +1 + n, cmp);
    int p = 1;
    for(int i = 1; i <= tot; ++i) {
        rt[i] = rt[i - 1];
        while(p <= n && v[r[p]] == i) update(rt[i], r[p]), ++p;
    }
    ll ans = 0;
    for(int T = 1; T <= m; ++T) {
        int u = read(), l = read(), r = read();
        int x = l,y = r;
        l = min((x + ans) % A, (y + ans) % A);
        r = max((x + ans) % A, (y + ans) % A);
        l = lower_bound(b + 1, b + 1 + tot, l) - b;
        r = upper_bound(b + 1, b + 1 + tot, r) - b - 1;
    //    printf("u=%d,l=%d,r=%d %d\n",u, l,r, tot);
        writeln(ans = solve(u, l, r));
    }
    return 0;
}