独立写出来+想出来的,1.5h就切了~
建立点分树,然后用 $vector$ 暴力存所有子节点,然后二分一下子就可以了.
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 300000
#define ll long long
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
using namespace std;
int edges,n;
int hd[N],to[N<<1],nex[N<<1],val[N<<1];
void add(int u,int v,int c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}
namespace tree
{
int size[N],son[N],top[N],fa[N],dep[N],dis[N];
void dfs1(int u,int ff)
{
fa[u]=ff,size[u]=1;
for(int i=hd[u];i;i=nex[i])
if(to[i]!=ff)
{
dep[to[i]]=dep[u]+1,dis[to[i]]=dis[u]+val[i];
dfs1(to[i],u);
size[u]+=size[to[i]];
if(size[to[i]]>size[son[u]]) son[u]=to[i];
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=hd[u];i;i=nex[i])
if(to[i]!=son[u]&&to[i]!=fa[u])
dfs2(to[i],to[i]);
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
int Dis(int x,int y)
{
return dis[x]+dis[y]-(dis[LCA(x,y)]<<1);
}
};
int root,sn;
int age[N],size[N],mx[N],vis[N],Fa[N];
struct Node
{
int v,d;
ll tot;
Node(int v=0,int d=0,ll tot=0):v(v),d(d),tot(tot){}
};
vector<Node>G[N],F[N];
bool cmp(Node a,Node b)
{
return a.v<b.v;
}
void getroot(int u,int ff)
{
size[u]=1,mx[u]=0;
for(int i=hd[u];i;i=nex[i])
if(to[i]!=ff&&!vis[to[i]])
getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]);
mx[u]=max(mx[u],sn-size[u]);
if(mx[u]<mx[root]) root=u;
}
void dfs(int u,int ff,int rt,int dep)
{
G[rt].push_back(Node(age[u],dep,0));
if(Fa[rt]) F[rt].push_back(Node(age[u],tree::Dis(Fa[rt],u), 0));
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||vis[v]) continue;
dfs(v,u,rt,dep+val[i]);
}
}
void solve(int u)
{
vis[u]=1;
G[u].push_back(Node(-100,0,0));
F[u].push_back(Node(-100,0,0));
G[u].push_back(Node(1000000004,0,0));
F[u].push_back(Node(1000000004,0,0));
dfs(u,0,u,0);
sort(G[u].begin(),G[u].end(),cmp);
sort(F[u].begin(),F[u].end(),cmp);
for(int i=1;i<F[u].size();++i) F[u][i].tot=F[u][i-1].tot+1ll*F[u][i].d;
for(int i=1;i<G[u].size();++i) G[u][i].tot=G[u][i-1].tot+1ll*G[u][i].d;
for(int i=hd[u];i;i=nex[i])
if(!vis[to[i]])
{
sn=size[to[i]],root=0,getroot(to[i],u),Fa[root]=u, solve(root);
}
}
ll work(int L,int R,int u)
{
ll re=0;
int l,r,mid,ans1=0,ans2=0;
l=0,r=G[u].size()-1;
while(l<=r)
{
mid=(l+r)>>1;
if(G[u][mid].v>=L) ans1=mid,r=mid-1;
else l=mid+1;
}
l=0,r=G[u].size()-1;
while(l<=r)
{
mid=(l+r)>>1;
if(G[u][mid].v<=R) ans2=mid,l=mid+1;
else r=mid-1;
}
if(ans1>0&&ans2<G[u].size()-1&&ans1<=ans2)
re+=G[u][ans2].tot-G[u][ans1-1].tot;
int U=u;
for(;Fa[u];u=Fa[u])
{
int anss1=ans1,anss2=ans2;
l=0,r=G[Fa[u]].size()-1,ans1=0;
while(l<=r)
{
mid=(l+r)>>1;
if(G[Fa[u]][mid].v>=L) ans1=mid,r=mid-1;
else l=mid+1;
}
l=0,r=G[Fa[u]].size()-1,ans2=0;
while(l<=r)
{
mid=(l+r)>>1;
if(G[Fa[u]][mid].v<=R) ans2=mid,l=mid+1;
else r=mid-1;
}
if(ans1>ans2) continue;
ll tmp=0;
tmp+=G[Fa[u]][ans2].tot-G[Fa[u]][ans1-1].tot;
if(anss2>=anss1) tmp-=F[u][anss2].tot-F[u][anss1-1].tot;
if(anss1<=anss2)
tmp=tmp+(ll)(ans2-ans1-(anss2-anss1+1)+1)*1ll*tree::Dis(U,Fa[u]);
else
tmp=tmp+(ll)(ans2-ans1+1)*1ll*tree::Dis(U,Fa[u]);
re+=tmp;
}
return re;
}
int main()
{
// setIO("input");
int Q,A,i,j;
scanf("%d%d%d",&n,&Q,&A);
for(i=1;i<=n;++i) scanf("%d",&age[i]);
for(i=1;i<n;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c),add(b,a,c);
}
tree::dfs1(1,0);
tree::dfs2(1,1);
mx[0]=sn=n,getroot(1,0),solve(root);
ll lastans=0;
for(int cas=1;cas<=Q;++cas)
{
int u,a,b,L,R;
scanf("%d%d%d",&u,&a,&b);
L=(a+lastans)%A,R=(b+lastans)%A;
if(L>R) swap(L,R);
printf("%lld\n",lastans=work(L,R,u));
}
return 0;
}