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; }