记录编号 365917 评测结果 AAAAAAAAAA
题目名称 [HNOI 2015]开店 最终得分 100
用户昵称 Gravatar‎MistyEye 是否通过 通过
代码语言 C++ 运行时间 20.337 s
提交时间 2017-01-22 07:23:51 内存使用 19.36 MiB
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 150005, maxd = 20;
struct Edge {
	int next, to, dis;
	Edge(int a=0, int b=0, int c=0) :
		next(a), to(b), dis(c) {}
} e[maxn<<1];
int head[maxn], tot;
void Add(int u, int v, int w) {
	e[++tot] = Edge(head[u], v, w); head[u] = tot;
}
int N, Q, A, age[maxn];
int size[maxn], vis[maxn], root, Size, F;
int dis[maxn][maxd], fa[maxn], res[maxn], sub[maxn][maxd];
struct Node {
	ll d;int g;
	Node(int a=0, int b=0) : d(a), g(b){}
	bool operator < (const Node& x) const {
		return g < x.g;
	}
};
vector<Node> vt[maxn], vtt[maxn][maxd];
void print(vector<Node>& v) {
	for(int i=0; i<(int)v.size(); ++i)
		printf("(%d,%d)", v[i].d, v[i].g); puts("");
}
int search(vector<Node>&v, int p) {
	int l = 0, r = v.size()-1, mid, ans = -1;
	while(l<=r) {
		mid = (l+r)>>1;
		if(v[mid].g<=p) ans = mid, l = mid+1;
		else r = mid-1;
	}
	return ans;
}
ll solve(vector<Node>&v, int l, int r, int d) {
	int ri = search(v, r), le = search(v, l-1);
	// print(v);
	// printf("%d], %d] \n", le, ri);
	if(ri<0) return 0;
	if(le>=0) return 1LL*(v[ri].d-v[le].d)+1LL*(ri-le)*d;
	else return 1LL*v[ri].d+1LL*(ri+1)*d;
}
ll query(int x, int l, int r) {
	// printf("query %d %d %d\n", x, l, r);
	ll ans = solve(vt[x], l, r, 0); 
	// printf("%lld ans <<\n", ans);
	for(int y=fa[x], rs=res[x]-1; y; y=fa[y], --rs) {
		// printf("x %d fa %d res %d sub %d dis %d\n", x, y, rs, sub[x][rs], dis[x][rs]);
		ans += solve(vt[y], l, r, dis[x][rs]);
		// printf(">>> %d\n", solve(vt[y], l, r, dis[x][rs]));
		ans -= solve(vtt[sub[x][rs]][rs], l, r, dis[x][rs]);
		// printf(">>> %d\n", solve(vtt[sub[x][rs]][rs], l, r, dis[x][rs]));
		// printf("%lld ans <<\n", ans);
	}
	return ans;
}
void getdep(int x, int fa, int Sub, int Rt) {
	int r = res[Rt];
	sub[x][r] = Sub; //printf("%d %d %d %d\n", Rt, r, x, Sub);
	vt[Rt].push_back(Node(dis[x][r], age[x]));
	vtt[Sub][r].push_back(Node(dis[x][r], age[x]));
	// printf("%d %d\n", x, fa); print(vt[Rt]);
	for(int i=head[x]; i; i=e[i].next) {
		int to = e[i].to;
		if(vis[to] || to==fa) continue;
		dis[to][r] = dis[x][r]+e[i].dis;
		getdep(to, x, Sub, Rt);
	}
}
void sumup(vector<Node>& v) {
	sort(v.begin(), v.end());
	// print(v);
	for(int i=1; i<(int)v.size(); ++i)
		v[i].d += v[i-1].d;
}
void build(int x) {
	int r = res[x];
	vt[x].push_back(Node(0, age[x]));
	for(int i=head[x]; i; i=e[i].next) {
		int to = e[i].to;
		if(vis[to]) continue;
		dis[to][r] = e[i].dis;
		getdep(to, x, to, x);
		sumup(vtt[to][r]);
	}
	// puts("VT");
	sumup(vt[x]);
}
int getroot(int x, int fa) {
	int f = 0; size[x] = 1;
	for(int i=head[x]; i; i=e[i].next) {
		int to = e[i].to;
		if(vis[to] || to==fa) continue;
		size[x] += getroot(to, x);
		f = max(f, size[to]);
	} 
	f = max(f, Size-size[x]);
	if(f<=F) F = f, root = x;
	return size[x];
}
void Build(int x) {
	// printf("------------%d-%d--------\n", x, res[x]);
	vis[x] = 1; build(x);
	for(int i=head[x]; i; i=e[i].next) {
		int to = e[i].to;
		if(vis[to]) continue;
		F = Size = size[to]; getroot(to, x);
		fa[root] = x;
		res[root] = res[x]+1;
		Build(root);
	}
}
int main() {	
	freopen("shop_hnoi2015.in","r",stdin);
	freopen("shop_hnoi2015.out","w",stdout);
	scanf("%d%d%d", &N, &Q, &A);
	for(int i=1; i<=N; ++i) scanf("%d", age+i);
	for(int i=1,a,b,c; i<N; ++i) {
		scanf("%d%d%d", &a, &b, &c);
		Add(a, b, c); Add(b, a, c);
	}
	F = Size = N; getroot(1, -1);
	res[root] = 1; Build(root);
	ll ans = 0;
	for(int i=1,x,a,b,l,r; i<=Q; ++i) {
		scanf("%d%d%d", &x, &a, &b);
		l = min((a+ans)%A, (b+ans)%A);
		r = max((a+ans)%A, (b+ans)%A);
		ans = query(x, l, r);
		printf("%lld\n", ans);
	}
	return 0;
}