题解:动态点分治
建立点分树
每个点维护点分树子树内节点到这个节点和父亲节点距离的前缀和
二分查找锁定合法区间
对每个祖先分治中心查询路径和然后减去不合法子树内的路径和
注意:求大量LCA时用树剖
不开O2时少用STL
相乘炸int
lower_bound和upper_bound返回值边界
注意常数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=200009;
const int oo=1000000000;
typedef long long Lint;
int n,T,u;
int a[maxn];
int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1],dist[maxn<<1];
void Addedge(int x,int y,int z){
nex[++cntedge]=head[x];
to[cntedge]=y;
dist[cntedge]=z;
head[x]=cntedge;
}
int nowsiz,root;
int vis[maxn];
int siz[maxn],g[maxn];
void Getsiz(int x,int fa){
siz[x]=1;
for(int i=head[x];i;i=nex[i]){
if(vis[to[i]])continue;
if(to[i]==fa)continue;
Getsiz(to[i],x);
siz[x]+=siz[to[i]];
}
}
void Getroot(int x,int fa){
siz[x]=1;
g[x]=0;
for(int i=head[x];i;i=nex[i]){
if(vis[to[i]])continue;
if(to[i]==fa)continue;
Getroot(to[i],x);
siz[x]+=siz[to[i]];
g[x]=max(g[x],siz[to[i]]);
}
g[x]=max(g[x],nowsiz-siz[x]);
if(g[x]<g[root])root=x;
}
int divfa[maxn];
void Sol(int x){
vis[x]=1;
Getsiz(x,0);
for(int i=head[x];i;i=nex[i]){
if(vis[to[i]])continue;
root=0;nowsiz=siz[to[i]];
Getroot(to[i],x);
divfa[root]=x;
Sol(root);
}
}
int father[maxn],dep[maxn],d[maxn],top[maxn],hson[maxn];
void Dfs(int x,int fa){
father[x]=fa;
dep[x]=dep[fa]+1;
siz[x]=1;
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa)continue;
d[to[i]]=d[x]+dist[i];
Dfs(to[i],x);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[hson[x]])hson[x]=to[i];
}
}
void Dfs2(int x,int toppoint){
top[x]=toppoint;
if(!hson[x])return;
Dfs2(hson[x],toppoint);
for(int i=head[x];i;i=nex[i]){
if(to[i]==father[x])continue;
if(to[i]==hson[x])continue;
Dfs2(to[i],to[i]);
}
}
int Getlca(int u,int v){
int tu=top[u];
int tv=top[v];
while(tu!=tv){
if(dep[tu]<dep[tv]){
swap(u,v);
swap(tu,tv);
}
u=father[tu];
tu=top[u];
}
if(dep[u]<dep[v])return u;
else return v;
}
int Getdist(int x,int y){
if((x==0)||(y==0))return 0;
int lca=Getlca(x,y);
return d[x]+d[y]-d[lca]-d[lca];
}
vector<int>G[maxn];
vector<Lint>S[maxn];
vector<Lint>S2[maxn];
int cmp(const int &rhs1,const int &rhs2){
return a[rhs1]<a[rhs2];
}
int main(){
scanf("%d%d%d",&n,&T,&u);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<n;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Addedge(x,y,z);
Addedge(y,x,z);
}
Dfs(1,0);
Dfs2(1,1);
g[0]=oo;root=0;nowsiz=n;
Getroot(1,0);
Sol(root);
for(int i=1;i<=n;++i){
int x=i;
while(x){
G[x].push_back(i);
x=divfa[x];
}
}
// for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// cout<<Getdist(i,j)<<' ';
// }
// cout<<endl;
// }
for(int i=1;i<=n;++i){
sort(G[i].begin(),G[i].end(),cmp);
Lint now=0,now2=0;
for(int j=0;j<G[i].size();++j){
now=now+Getdist(i,G[i][j]);
now2=now2+Getdist(divfa[i],G[i][j]);
S[i].push_back(now);
S2[i].push_back(now2);
G[i][j]=a[G[i][j]];
}
// printf("=->%d %d %d\n",i,now,now2);
}
// for(int i=1;i<=n;++i)cout<<d[i]<<' ';
// cout<<endl;
Lint ans=0;
while(T--){
int x,y,Lold,Rold;
scanf("%d%d%d",&x,&Lold,&Rold);
y=x;
int t1=(Lold+ans)%u;
int t2=(Rold+ans)%u;
Lold=min(t1,t2);
Rold=max(t1,t2);
// cout<<Lold<<' '<<Rold<<endl;
ans=0;
int p=0;
// cout<<ans<<endl;
// for(int i=0;i<G[x].size();++i)cout<<G[x][i]<<' ';
// cout<<endl;
p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
if(p>-1)ans+=S[x][p];
// cout<<p<<endl;
p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
if(p)ans-=S[x][p-1];
// cout<<p<<endl;
// cout<<ans<<endl;
while(divfa[x]){
Lint fdist=Getdist(divfa[x],y);
int fa=divfa[x];
p=upper_bound(G[fa].begin(),G[fa].end(),Rold)-G[fa].begin()-1;
if(p>-1)ans+=S[fa][p]+fdist*(p+1);
// cout<<p<<' ';
p=lower_bound(G[fa].begin(),G[fa].end(),Lold)-G[fa].begin();
if(p)ans-=S[fa][p-1]+fdist*p;
// cout<<p<<endl;
// cout<<ans<<endl;
p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
if(p>-1)ans-=S2[x][p]+fdist*(p+1);
p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
if(p)ans+=S2[x][p-1]+fdist*p;
// cout<<ans<<endl;
x=divfa[x];
}
printf("%lld\n",ans);
}
return 0;
}