Description

风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到

人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的
想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面
向什么样的人群。很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n
个地方,编号为 1 到 n,被 n-1 条带权的边连接起来。每个地方都住着一个妖怪,
其中第 i 个地方的妖怪年龄是 x_i。妖怪都是些比较喜欢安静的家伙,所以它们并
不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 3。妖怪和人一
样,兴趣点随着年龄的变化自然就会变化,比如我们的 18 岁少女幽香和八云紫就
比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以
幽香打算选择一个地方 u(u为编号),然后在 u开一家面向年龄在 L到R 之间(即
年龄大于等于 L、小于等于 R)的妖怪的店。也有可能 u这个地方离这些妖怪比较
远,于是幽香就想要知道所有年龄在 L 到 R 之间的妖怪,到点 u 的距离的和是多
少(妖怪到 u 的距离是该妖怪所在地方到 u 的路径上的边的权之和) ,幽香把这个
称为这个开店方案的方便值。幽香她们还没有决定要把店开在哪里,八云紫倒是准
备了很多方案,于是幽香想要知道,对于每个方案,方便值是多少呢。


Solution

我们将答案变成【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_离线的答案减去【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_点集_02的答案,于是我们询问的点集变成了一个前缀和。
设询问的点集为【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_点集_03【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_#define_04表示【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_#define_05到根的距离,那么答案为:
【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_点集_06

关于求【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_点集_07,在LNOI2014 LCA这题中,我们有一个离线做法,就是将点集中的点依次加入,将其到根路径上的点全部加一,询问【BZOJ4012】【HNOI2015】开店(树链剖分,主席树)_#define_05到根路径上的权值和即为答案。
LNOI2014LCA是允许离线的。如果要求在线,我们用主席树搞即可。由于要资瓷区间加,所以要搞一个标记永久化。


Code

/************************************************
 * Au: Hany01
 * Date: Sep 12th, 2018
 * Prob: BZOJ4012 HNOI2015 开店

 * Inst: Yali High School
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(), a.end()
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read() {
	static int _, __; static char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 15e4 + 5, maxm = 3e5 + 5;

int n, q, MOD, ls[maxn], lss, beg[maxn], nex[maxm], v[maxm], w[maxm], e = 1, W[maxn], dep[maxn], sz[maxn], fa[maxn], top[maxn], son[maxn], dfn[maxn], rt[maxn], clk, cnt[maxn];
LL diss[maxn], dis[maxn], sumW[maxn];
PII node[maxn];

inline void add(int uu, int vv, int ww) { v[++ e] = vv, w[e] = ww, nex[e] = beg[uu], beg[uu] = e; }

void DFS1(int u, int pa) {
	dep[u] = dep[fa[u] = pa] + 1, sz[u] = 1;
	for (register int i = beg[u]; i; i = nex[i]) if (v[i] != pa)
		dis[v[i]] = dis[u] + (W[v[i]] = w[i]), DFS1(v[i], u), sz[u] += sz[v[i]], son[u] = sz[son[u]] < sz[v[i]] ? v[i] : son[u];
}

void DFS2(int u) {
	dfn[u] = ++ clk, sumW[clk] = sumW[clk - 1] + W[u];
	if (son[u]) top[son[u]] = top[u], DFS2(son[u]);
	for (register int i = beg[u]; i; i = nex[i])
		if (v[i] != fa[u] && v[i] != son[u]) top[v[i]] = v[i], DFS2(v[i]);
}

struct SegmentTree {
#define mid ((l + r) >> 1)
	int tot;
	struct Node { int lc, rc, tag; LL sum; } tr[maxn * 55];
	void update(int &t, int las, int l, int r, int x, int y) {
		tr[t = ++ tot] = tr[las], tr[t].sum += sumW[min(r, y)] - sumW[max(l, x) - 1];
		if (x <= l && r <= y) { ++ tr[t].tag; return; }
		if (x <= mid) update(tr[t].lc, tr[las].lc, l, mid, x, y);
		if (y >  mid) update(tr[t].rc, tr[las].rc, mid + 1, r, x, y);
	}
	LL query(int t, int l, int r, int x, int y, int tags) {
		if (x <= l && r <= y) return tr[t].sum + (LL)tags * (sumW[r] - sumW[l - 1]);
		tags += tr[t].tag;
		if (y <= mid) return query(tr[t].lc, l, mid, x, y, tags);
		if (x >  mid) return query(tr[t].rc, mid + 1, r, x, y, tags);
		return query(tr[t].lc, l, mid, x, y, tags) + query(tr[t].rc, mid + 1, r, x, y, tags);
	}
}ST;

inline void insert(int i, int u) {
	for (; top[u] != 1; u = fa[top[u]]) ST.update(rt[i], rt[i], 1, n, dfn[top[u]], dfn[u]);
	ST.update(rt[i], rt[i], 1, n, 1, dfn[u]);
}

inline LL ask(int t1, int t2, int u) {
	LL ans = 0;
	for (; top[u] != 1; u = fa[top[u]])
		ans += ST.query(t2, 1, n, dfn[top[u]], dfn[u], 0) - ST.query(t1, 1, n, dfn[top[u]], dfn[u], 0);
	return ans + ST.query(t2, 1, n, 1, dfn[u], 0) - ST.query(t1, 1, n, 1, dfn[u], 0);
}

int main()
{
#ifdef hany01
	freopen("bzoj4012.in", "r", stdin);
	freopen("bzoj4012.out", "w", stdout);
#endif

	static int uu, vv, ww, cur, l, r, u;
	static LL ans;

	n = read(), q = read(), MOD = read();
	For(i, 1, n) node[i] = mp(ls[i] = read(), i);
	sort(ls + 1, ls + 1 + n), lss = unique(ls + 1, ls + 1 + n) - ls - 1;
	For(i, 1, n) node[i].x = lower_bound(ls + 1, ls + 1 + lss, node[i].x) - ls;
	For(i, 2, n) uu = read(), vv = read(), ww = read(), add(uu, vv, ww), add(vv, uu, ww);

	DFS1(1, 0), top[1] = 1, DFS2(1);

	sort(node + 1, node + 1 + n);
	For(i, 1, lss)
		for (rt[i] = rt[i - 1], diss[i] = diss[i - 1], cnt[i] = cnt[i - 1]; cur < n && node[cur + 1].x <= i; )
			insert(i, node[++ cur].y), diss[i] += dis[node[cur].y], ++ cnt[i];

	while (q --) {
		u = read(), l = (read() + ans % MOD) % MOD, r = (read() + ans % MOD) % MOD;
		if (l > r) swap(l, r);
		l = lower_bound(ls + 1, ls + 1 + lss, l) - ls, r = upper_bound(ls + 1, ls + 1 + lss, r) - ls - 1;
		printf("%lld\n", ans = (diss[r] - diss[l - 1] + (LL)dis[u] * (cnt[r] - cnt[l - 1]) - ask(rt[l - 1], rt[r], u) * 2));
	}

	return 0;
}

/************************************************
 * Au: Hany01
 * Date: Sep 12th, 2018
 * Prob: BZOJ4012 HNOI2015 开店
 * Email: hany01dxx@gmail.com & hany01@foxmail.com
 * Inst: Yali High School
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(), a.end()
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read() {
	static int _, __; static char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 15e4 + 5, maxm = 3e5 + 5;

int n, q, MOD, ls[maxn], lss, beg[maxn], nex[maxm], v[maxm], w[maxm], e = 1, W[maxn], dep[maxn], sz[maxn], fa[maxn], top[maxn], son[maxn], dfn[maxn], rt[maxn], clk, cnt[maxn];
LL diss[maxn], dis[maxn], sumW[maxn];
PII node[maxn];

inline void add(int uu, int vv, int ww) { v[++ e] = vv, w[e] = ww, nex[e] = beg[uu], beg[uu] = e; }

void DFS1(int u, int pa) {
	dep[u] = dep[fa[u] = pa] + 1, sz[u] = 1;
	for (register int i = beg[u]; i; i = nex[i]) if (v[i] != pa)
		dis[v[i]] = dis[u] + (W[v[i]] = w[i]), DFS1(v[i], u), sz[u] += sz[v[i]], son[u] = sz[son[u]] < sz[v[i]] ? v[i] : son[u];
}

void DFS2(int u) {
	dfn[u] = ++ clk, sumW[clk] = sumW[clk - 1] + W[u];
	if (son[u]) top[son[u]] = top[u], DFS2(son[u]);
	for (register int i = beg[u]; i; i = nex[i])
		if (v[i] != fa[u] && v[i] != son[u]) top[v[i]] = v[i], DFS2(v[i]);
}

struct SegmentTree {
#define mid ((l + r) >> 1)
	int tot;
	struct Node { int lc, rc, tag; LL sum; } tr[maxn * 55];
	void update(int &t, int las, int l, int r, int x, int y) {
		tr[t = ++ tot] = tr[las], tr[t].sum += sumW[min(r, y)] - sumW[max(l, x) - 1];
		if (x <= l && r <= y) { ++ tr[t].tag; return; }
		if (x <= mid) update(tr[t].lc, tr[las].lc, l, mid, x, y);
		if (y >  mid) update(tr[t].rc, tr[las].rc, mid + 1, r, x, y);
	}
	LL query(int t, int l, int r, int x, int y, int tags) {
		if (x <= l && r <= y) return tr[t].sum + (LL)tags * (sumW[r] - sumW[l - 1]);
		tags += tr[t].tag;
		if (y <= mid) return query(tr[t].lc, l, mid, x, y, tags);
		if (x >  mid) return query(tr[t].rc, mid + 1, r, x, y, tags);
		return query(tr[t].lc, l, mid, x, y, tags) + query(tr[t].rc, mid + 1, r, x, y, tags);
	}
}ST;

inline void insert(int i, int u) {
	for (; top[u] != 1; u = fa[top[u]]) ST.update(rt[i], rt[i], 1, n, dfn[top[u]], dfn[u]);
	ST.update(rt[i], rt[i], 1, n, 1, dfn[u]);
}

inline LL ask(int t1, int t2, int u) {
	LL ans = 0;
	for (; top[u] != 1; u = fa[top[u]])
		ans += ST.query(t2, 1, n, dfn[top[u]], dfn[u], 0) - ST.query(t1, 1, n, dfn[top[u]], dfn[u], 0);
	return ans + ST.query(t2, 1, n, 1, dfn[u], 0) - ST.query(t1, 1, n, 1, dfn[u], 0);
}

int main()
{
#ifdef hany01
	freopen("bzoj4012.in", "r", stdin);
	freopen("bzoj4012.out", "w", stdout);
#endif

	static int uu, vv, ww, cur, l, r, u;
	static LL ans;

	n = read(), q = read(), MOD = read();
	For(i, 1, n) node[i] = mp(ls[i] = read(), i);
	sort(ls + 1, ls + 1 + n), lss = unique(ls + 1, ls + 1 + n) - ls - 1;
	For(i, 1, n) node[i].x = lower_bound(ls + 1, ls + 1 + lss, node[i].x) - ls;
	For(i, 2, n) uu = read(), vv = read(), ww = read(), add(uu, vv, ww), add(vv, uu, ww);

	DFS1(1, 0), top[1] = 1, DFS2(1);

	sort(node + 1, node + 1 + n);
	For(i, 1, lss)
		for (rt[i] = rt[i - 1], diss[i] = diss[i - 1], cnt[i] = cnt[i - 1]; cur < n && node[cur + 1].x <= i; )
			insert(i, node[++ cur].y), diss[i] += dis[node[cur].y], ++ cnt[i];

	while (q --) {
		u = read(), l = (read() + ans % MOD) % MOD, r = (read() + ans % MOD) % MOD;
		if (l > r) swap(l, r);
		l = lower_bound(ls + 1, ls + 1 + lss, l) - ls, r = upper_bound(ls + 1, ls + 1 + lss, r) - ls - 1;
		printf("%lld\n", ans = (diss[r] - diss[l - 1] + (LL)dis[u] * (cnt[r] - cnt[l - 1]) - ask(rt[l - 1], rt[r], u) * 2));
	}

	return 0;
}