独立写出来+想出来的,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 ",lastans=work(L,R,u)); } return 0; }