這是一種類型的動態點分治
動態點分治,關鍵還是要在均攤n的空間複雜度內存下所有東西。這個就要充分利用stl,比如vector
每一個點存以這個點爲根點分治的信息。
對於詢問一個點的路徑時,就是沿着點分治樹,不斷朝fa走,每走一層統計一下,因爲分治樹可以保證在log層內,時間複雜度同階
卡常數
無優化:43848ms
優化一:取模優化(x-=mod 代替 % ) + 循環展開+ 一部分inline :43612ms
第三次:將i++改爲++i:速度稍減慢,dfs(int &u)佔位符加速也沒有體現出來
優化不下去了
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<utility>
#define fi first
#define se second
#define pii pair<int,int>
#define MK(a,b) make_pair((a),(b))
using namespace std;
typedef long long ll;
const int N=150005;
inline int read()
{
int ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
int n,Q,A;ll ans;
int U,L,R;
/////////////////////
struct bian
{
int to[N*2],pre[N*2],dis[N*2],head[N],tot;
void addedge(int u,int v,int d)
{
to[++tot]=v;pre[tot]=head[u];head[u]=tot;dis[tot]=d;
}
}e;
//////////////////////
int age[N],fa[N];ll dis[N];
struct aa
{
int num;
vector< pair<int,pair<int,int> > >a;
vector< pair<int,ll> > ch[3];
int f(int u)
{
int l=0,r=a.size()-1,mid,ans;
while (l<=r)
{
mid=(l+r)>>1;
if (a[mid].fi>=u) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int dis(int u)
{
return a[f(u)].se.se;
}
int id(int u)
{
return a[f(u)].se.fi;
}
void init()
{
sort(a.begin(),a.end());
for (int i=0;i<num;i++)
{
sort(ch[i].begin(),ch[i].end());
int sz=ch[i].size();
for (int j=1;j<sz;j++) ch[i][j].se+=ch[i][j-1].se;
}
}
ll query(int u,int up)
{
int tid=id(u);ll tdis=dis(u),ans=0;
for (int i=0;i<num;i++)
if (tid!=i)
{
int pos=upper_bound(ch[i].begin(),ch[i].end(),MK(up,(ll)(1e16)))-ch[i].begin();
if (pos==0) continue;
ans+=(ll)pos*tdis;
ans+=ch[i][pos-1].se;
}
return ans;
}
}tt[N];
/////////////
int size[N],sum,mi,rt;
bool b[N];
void get_size(int u,int fat)
{
int v;size[u]=1;
for (int i=e.head[u];i;i=e.pre[i])
{
v=e.to[i];
if (!b[v]&&v!=fat)
{
get_size(v,u);
size[u]+=size[v];
}
}
}
void get_rt(int u,int fat)
{
int v,mx=sum-size[u];
for (int i=e.head[u];i;i=e.pre[i])
{
v=e.to[i];
if (!b[v]&&v!=fat)
{
get_rt(v,u);
mx=max(mx,size[v]);
}
}
if (mx<mi) rt=u,mi=mx;
}
queue<int> q;
void dfs2(int u,int fat,int d)
{
int v;
dis[u]=d;q.push(u);
for (int i=e.head[u];i;i=e.pre[i])
{
v=e.to[i];
if (!b[v]&&v!=fat) dfs2(v,u,d+e.dis[i]);
}
}
void work(int u)
{
int v,&num=tt[u].num;
tt[u].a.push_back(MK(u,MK(-1,0)));
for (int i=e.head[u];i;i=e.pre[i])
{
v=e.to[i];
if (!b[v])
{
dfs2(v,u,e.dis[i]);
while (!q.empty())
{
v=q.front();q.pop();
tt[u].a.push_back(MK(v,MK(num,dis[v])));
tt[u].ch[num].push_back(MK(age[v],dis[v]));
}
num++;
}
}
tt[u].init();
}
void dfs(int u,int fat)
{
get_size(u,0);sum=size[u];mi=1e7;
get_rt(u,0);u=rt;
b[u]=true;fa[u]=fat;work(u);
for (int i=e.head[u];i;i=e.pre[i])
if (!b[e.to[i]]) dfs(e.to[i],u);
}
///////////////////////////////////////////
void init()
{
n=read(),Q=read(),A=read();
for (int i=1;i<=n;i++) age[i]=read();
int xx,yy,zz;
for (int i=1;i<n;i++)
{
xx=read(),yy=read(),zz=read();
e.addedge(xx,yy,zz);
e.addedge(yy,xx,zz);
}
dfs(1,0);
}
ll query(int u,int up)
{
if (up<0) return 0;
ll ans=0;
while (u)
{
if (age[u]<=up) ans+=tt[u].dis(U);
ans+=tt[u].query(U,up),u=fa[u];
}
return ans;
}
int main()
{
init();
for (int i=1;i<=Q;i++)
{
U=read(),L=read(),R=read();
L=(L+ans)%A,R=(R+ans)%A;
if (L>R) swap(L,R);
ans=
query(U,R)-
query(U,L-1);
printf("%lld\n",ans);
ans=ans%A;
}
return 0;
}