题意:求“方便值”
思路:树链剖分维护修改即可,似乎还有点分树的做法~
#include<bits/stdc++.h>
#define int long long
#define debug(x) cout<<"debug:"<<x<<endl
using namespace std;
inline int read(){
int q=0,f=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;ch = getchar();
}
while(isdigit(ch)){
q=q*10+ch-'0';ch=getchar();
}
return q*f;
}
const int maxn = 300010*2;
const int inf = 0x3f3f3f3f;
int n,m;
int cnt;
int idx;
int rt[maxn];
int size;
int ans;
int head[maxn];
int nxt[maxn];
int ver[maxn];
int w[maxn];
int siz[maxn];
int fa[maxn];
int top[maxn];
int dfn[maxn];
int Last[maxn];
int root;
inline void add(int u,int v,int wi){
ver[++cnt] = v;
nxt[cnt] = head[u];head[u] = cnt;
w[cnt] = wi;
return;
}
struct node
{
int v;
int id;
}a[maxn];
inline bool operator < (node l,node r){
return l.v == r.v ? l.id < r.id:l.v < r.v;
}
int dep[maxn];
int Dep[maxn];
#define travel(x) for(int i = head[x];i;i=nxt[i])
inline void dfs1(int x,int f){
siz[x] = 1;
fa[x] = f;
travel(x){
int y = ver[i];
if(y != f){
dep[y] = dep[x] + w[i];
Last[y] = w[i];
dfs1(y,x);
siz[x] += siz[y];
}
}
}
int E[maxn];
inline void dfs2(int x,int f){
dfn[x] = ++idx;
E[dfn[x]] = Last[x];
int mx = 0;
int tmp = 0;
travel(x){
int y = ver[i];
if(y != f && siz[y] > mx){
tmp = y;
mx = siz[y];
}
}
if(!tmp) return;
top[tmp] = top[x];
dfs2(tmp,x);
travel(x){
int y = ver[i];
if(y != f && y != tmp){
top[y] = y;
dfs2(y,x);
}
}
}
const int maxm = 8e6+10;
int ls[maxm];
int rs[maxm];
int sum[maxm];
int tot[maxm];
inline void modify(int l,int r,int L,int R,int &p,int v){
p = ++size;
ls[p] = ls[v];
rs[p] = rs[v];
sum[p] = sum[v];
tot[p] = tot[v];
if(l == L && r == R){
++tot[p];
return;
}
sum[p] += E[r] - E[l - 1];
int mid = (L + R) >> 1;
if(r <= mid){
modify(l,r,L,mid,ls[p],ls[v]);
}
else if(mid +1 <= l){
modify(l,r,mid+1,R,rs[p],rs[v]);
}
else {
modify(l,mid,L,mid,ls[p],ls[v]);
modify(mid+1,r,mid+1,R,rs[p],rs[v]);
}
}
inline int get_ans(int l,int r,int L,int R,int p){
int res = (E[r] - E[l - 1])*tot[p];
if(l == L && r == R){
return res + sum[p];
}
int mid = (L + R) >> 1;
if(r <= mid){
return res + get_ans(l,r,L,mid,ls[p]);
}
else if(mid + 1 <= l){
return res + get_ans(l,r,mid+1,R,rs[p]);
}
else{
return res + get_ans(l,mid,L,mid,ls[p]) + get_ans(mid+1,r,mid+1,R,rs[p]);
}
}
inline int get_rt(int p){
while(p){
modify(dfn[top[p]],dfn[p],1,n,root,root);
p = fa[top[p]];
}
return root;
}
inline int query(int Rt,int p){
int res = 0;
while(p){
res += get_ans(dfn[top[p]],dfn[p],1,n,Rt);
//debug(res);
p = fa[top[p]];
}
return res;
}
int A;
inline void solve()
{
int x,y,z;
n = read(),m = read(),A = read();
for(int i = 1;i <= n; ++i){
a[i].v = read();
a[i].id = i;
}
sort(a+1,a+n+1);
for(int i = 1;i < n; ++i){
x = read(),y = read(),z = read();
add(x,y,z);
add(y,x,z);
}
dfs1(1,0),top[1] = 1;
dfs2(1,0);
for(int i = 1;i <= n; ++i){
E[i] += E[i - 1];
Dep[i] = Dep[i - 1] + dep[a[i].id];
///debug(Dep[i]);
}
for(int i = 1;i <= n; ++i){
rt[i] = get_rt(a[i].id);
//debug(rt[i]);
}
// for(int i = 1;i <= n; ++i)
// {
// debug(a[i].v);
// debug(a[i].id);
// }
//debug(ans);
while(m--){
z = read(),x = read(),y = read();
// debug(x);
// debug(y);
x = (1ll * x + ans)%A;
y = (1ll * y + ans) % A;
// debug(x);
// debug(y);
if(x > y){
swap(x,y);
}
x=lower_bound(a+1,a+1+n,(node){x,0})- a;
y=upper_bound(a+1,a+1+n,(node){y,inf})-a-1;
ans = (y - x + 1)*dep[z]+Dep[y] - Dep[x - 1];
//debug(ans);
ans -= 2ll*(query(rt[y],z) - query(rt[x - 1],z));
//debug(ans);
printf("%lld\n",ans);
}
return;
}
signed main(){solve();return 0;}