点分治:
记录每个分支根到它管辖所有节点的距离和颜色,按颜色排序后求前缀和。
#include
#include
#include
#include
#include
#define zw for (int i=head[u];i;i=e[i].next)
#define y e[i].b
#define INF 2147483647
#define N 150050
using namespace std;
typedef long long LL;
struct Edge{ int a,b,v,next; }e[2*N];
struct data{ int c;LL L;}identity;
vector F[N][5];
bool operator < (data p1,data p2) { return p1.c < p2.c; };
struct Monster{ int v; LL L; };
vector dis[N];
bool operator < (Monster p1,Monster p2) { return p1.v < p2.v; };
int head[N],cnt,n,Q,A;
bool vis[N];
int c[N],w[N],siz[N],u,a,b,L,R,sum,rt;
int bl1[N],bl2[N];
LL ans = 0LL;
void add(int a,int b,int v) {
e[++cnt].a = a;
e[cnt].b = b;
e[cnt].v = v;
e[cnt].next = head[a];
head[a] = cnt;
return ;
}
void get_rt(int u,int fa) {
w[u] = 0; siz[u] = 1;
zw if (!vis[y] && y != fa) {
get_rt(y,u);
siz[u] += siz[y];
w[u] = max(siz[y],w[u]);
}
w[u] = max(sum-siz[u],w[u]);
if (w[u] < w[rt]) rt = u;
return ;
}
int get_sum(int u,int fa) {
int tmp = 1;
zw
if (!vis[y] && y != fa)
tmp += get_sum(y,u);
return tmp;
}
void DFS(int u,int fa,int w1,int w2,int len) {
bl1[u] = w1; bl2[u] = w2;
zw if (y != fa && !vis[y]) {
F[w1][w2].push_back( (data){ c[y] , len+e[i].v } );
dis[w1].push_back( (Monster){ y , len+e[i].v } );
DFS(y,u,w1,w2,len + e[i].v);
}
return ;
}
void solve(int u) {
vis[u] = true; int son = 0;
dis[u].push_back( (Monster) {u,0} );
zw if (!vis[y]) {
++son;
F[u][son].push_back( (data) {0,0LL} );
F[u][son].push_back( (data) {c[y],e[i].v} );
dis[u].push_back( (Monster){y,e[i].v} );
DFS(y,u,u,son,e[i].v);
sort( F[u][son].begin() , F[u][son].end() );
for (int i=1;i 0);
int l = 0 , r = dis[u].size() - 1;
while (l < r) {
int mid = (l + r + 1) / 2;
int k = dis[u][mid].v;
if (dis[u][mid].v <= root) l = mid; else r = mid - 1;
}
return dis[u][l].L;
}
void get_ans(int u,int f,int root) {
LL tmp = 0LL;
LL DIS = get_dis(u,root);
if (L <= c[u] && c[u] <= R) ans += DIS;
for (int i=0;i<4;i++) if (bl2[f] != i && F[u][i].size()) {
int p1 = paul(u,i,L-1) , p2 = paul(u,i,R);
LL k = F[u][i][p2].L - F[u][i][p1].L;
ans += DIS * (p2 - p1) + k;
}
if (bl1[u]) get_ans(bl1[u],u,root);
return ;
}
int main()
{
//freopen("4012.in","r",stdin);
//freopen("4012.out","w",stdout);
//assert(0);
scanf("%d%d%d",&n,&Q,&A);
for (int i=1;i<=n;i++) scanf("%d",&c[i]) , c[i]++;
for (int i=1;i<=n-1;i++) {
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
add(a,b,v); add(b,a,v);
}
sum = n;
w[0] = INF;
rt = 0;
get_rt(1,1);
solve(rt);
bl2[0] = 5;
while (Q--) {
scanf("%d%d%d",&u,&a,&b);
L = (a + ans) % A; L++;
R = (b + ans) % A; R++;
if (L > R) swap(L,R);
ans = 0LL;
get_ans(u,0,u);
#ifdef ONLINE_JUDGE
printf("%lld\n",ans);
#else
printf("%I64d\n",ans);
#endif
}
//fclose(stdin);fclose(stdout);
return 0;
}