Problem:
Non-redundant Drive
The people of JAG kingdom hate redundancy. For example, the N cities in JAG kingdom are connected with just $N - 1$ bidirectional roads such that any city is reachable from any city through some roads. Under the condition, the number of paths from a city to another city is exactly one for all pairs of the cities. This is a non-redundant road network :)
One day, you, a citizen of JAG kingdom, decided to travel as many cities in the kingdom as possible with a car. The car that you will use has an infinitely large tank, but initially the tank is empty. The fuel consumption of your car is 1 liter per 1 km, i.e. it consumes 1 liter of gasoline to move 1 km.
Each city has exactly one gas station, and you can supply $g_x$ liters of gasoline to your car at the gas station of the city $x$. Of course, you have a choice not to visit some of the gas stations in your travel. But you will not supply gasoline twice or more at the same gas station, because it is redundant. Each road in the kingdom has a distance between two cities: the distance of $i$-th road is $d_i$ km. You will not pass the same city or the same road twice or more, of course, because it is redundant.
If a quantity of stored gasoline becomes zero, the car cannot move, and hence your travel will end there. But then, you may concern about an initially empty tank. Don't worry. You can start at any gas station of the cities in the kingdom. Furthermore, each road directly connects the gas stations of the its two ends (because the spirit of non-redundancy avoids redundant moves in a city), you therefore can supply gasoline to your car even if your car tank becomes empty just when you arrive the city.
Your task is to write a program computing the maximum number of cities so that you can travel under your non-redundancy policy.
Input
The input consists of a single test case.
$N$
$g_1$ $g_2$ ...  $g_N$
$a_1$ $b_1$ $d_1$
$a_2$ $b_2$ $d_2$
...
$a_{N-1}$ $b_{N-1}$ $d_{N-1}$
The first line contains an integer $N$ ($1 \leq N \leq 100,000$), which is the number of cities in JAG kingdom. The second line contains $N$ integers: the $i$-th of them is $g_i$ ($1 \leq g_i \leq 10,000$), the amount of gasoline can be supplied at the gas station of the city $i$. The following $N - 1$ lines give information of roads: the $j$-th line of them contains $a_j$ and $b_j$ , which indicates that the $j$-th road bidirectionally connects the cities $a_j$ and $b_j$ ($1 \leq a_j, b_j \leq N, a_j \ne b_j$) with distance $d_j$ ($1 \leq d_j \leq 10,000$). You can assume that all cities in the kingdom are connected by the roads.
Output
Print the maximum number of cities you can travel from any city under the constraint such that you can supply gasoline at most once per a gas station.
Sample Input 1
5
5 8 1 3 5
1 2 4
2 3 3
2 4 3
1 5 7
Output for the Sample Input 1
4
Sample Input 2
2
10 1
1 2 10
Output for the Sample Input 2
2
Sample Input 3
5
1 3 5 1 1
1 2 5
2 3 3
2 4 3
1 5 5
Output for the Sample Input 3
3

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B> void chmax(A& l, const B& r){ if(l < r) l = r; }
template <class A, class B> void chmin(A& l, const B& r){ if(r < l) l = r; }


void testcase(){
  ll N; cin >> N;
  V<ll> G(N); REP(i,N) cin >> G[i];
  V<V<pair<ll,ll>>> adj(N);
  REP(i,N-1){
    ll a,b,d; cin >> a >> b >> d; a--; b--;
    adj[a].push_back({b,d});
    adj[b].push_back({a,d});
  }
  
  V<ll> par(N, -1);
  V<ll> sz(N, 1);
  {
    auto dfs = [&](auto& dfs, ll v, ll p) -> void {
      for(auto [w,d] : adj[v]) if(w != p){
        par[w] = v; dfs(dfs, w, v); sz[v] += sz[w];
      }
    }; dfs(dfs, 0, -1);
  }
  auto findCentroid = [&](ll& v) -> void {
    while(1){
      ll nx = -1;
      for(auto [w,d] : adj[v]) if(sz[w] * 2 > sz[v]) nx = w;
      if(nx < 0) break;
      ll w = nx;
      par[v] = w; par[w] = -1;
      sz[v] -= sz[w]; sz[w] += sz[v];
      v = w;
    }
  };
  ll ans = 1;
  V<ll> req(N+2, INF);
  req[0] = -INF;
  auto update_req = [&](auto& dfs, ll v, ll minpt, ll pt, ll dist) -> void {
    chmin(minpt, pt);
    chmin(req[dist], -minpt);
    for(auto [w,d] : adj[v]) if(sz[w] && w != par[v]){
      dfs(dfs, w, minpt, pt+G[v]-d, dist+1);
    }
  };
  auto update_ans = [&](auto& dfs, ll v, ll bottom, ll pt, ll dist)-> void {
    if(0 <= bottom) chmax(ans, dist + ll(upper_bound(req.begin(), req.end(), pt) - req.begin()));
    for(auto [w,d] : adj[v]) if(sz[w] && w != par[v]){
      dfs(dfs, w, min<ll>(0, bottom + G[w] - d), pt+G[w]-d, dist+1);
    }
  };
  auto dfs = [&](auto& dfs, ll v) -> void {
    findCentroid(v);
    REP(tt,2){
      REP(i,sz[v]+1) req[i+1] = INF;
      for(auto [w,d] : adj[v]) if(sz[w]){
        update_ans(update_ans, w, min<ll>(0, G[w] - d), G[w]-d, 1);
        update_req(update_req, w, 0, G[v]-d, 1);
      }
      chmax(ans, ll(upper_bound(req.begin(), req.end(), 0) - req.begin()));
      reverse(adj[v].begin(), adj[v].end());
    }
    sz[v] = 0;
    for(auto [w,d] : adj[v]) if(sz[w]) { par[w] = -1; dfs(dfs, w); }
  };
  dfs(dfs, 0);
  cout << ans << "\n";
}

int main(){
  cin.tie(0)->sync_with_stdio(0);
  testcase();
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 18204
final_rank: 1

code_snippet: #include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
struct bian{
	int next,point,w;
}b[210000];
int p[110000],n,len,g[110000],pd[110000],size[110000],where,now,bo[110000],ans;
struct atom{
	int where,w;
	long long f;
};
vector<atom>A,B;
void ade(int k1,int k2,int k3){
	b[++len]=(bian){p[k1],k2,k3}; p[k1]=len;
}
void add(int k1,int k2,int k3){
	ade(k1,k2,k3); ade(k2,k1,k3);
}
int dfs1(int k1,int k2){
	size[k1]=1;
	for (int i=p[k1];i;i=b[i].next){
		int j=b[i].point;
		if (pd[j]==0&&j!=k2) size[k1]+=dfs1(j,k1);
	}
	return size[k1];
}
void dfs2(int k1,int k2){
	int num=n-size[k1];
	for (int i=p[k1];i;i=b[i].next){
		int j=b[i].point;
		if (pd[j]==0&&j!=k2){
			num=max(num,size[j]); dfs2(j,k1);
		}
	}
	if (now>num){
		now=num; where=k1;
	}
}
void dfs3(int k1,int k2,long long dis,long long mi,int size,int w){
	dis+=g[k1]; mi+=g[k1]; mi=min(mi,0ll);
//	cout<<k1<<" "<<k2<<" "<<dis<<" "<<mi<<" "<<size<<" "<<w<<endl;
	if (mi>=0)
		A.push_back((atom){w,size,dis});
	for (int i=p[k1];i;i=b[i].next){
		int j=b[i].point;
		if (j!=k2&&pd[j]==0)
			dfs3(j,k1,dis-b[i].w,mi-b[i].w,size+1,w);
	}
}
void dfs4(int k1,int k2,long long dis,long long mi,int size,int w){
	mi=min(mi,dis); dis+=g[k1];
	B.push_back((atom){w,size,mi});
	for (int i=p[k1];i;i=b[i].next){
		int j=b[i].point;
		if (j!=k2&&pd[j]==0) dfs4(j,k1,dis-b[i].w,mi,size+1,w);
	}
}
int compare(atom k1,atom k2){
	return k1.f<k2.f;
}
void solve(int k1){
	n=dfs1(k1,0); now=n+1; where=0; dfs2(k1,0); int k=where;
	bo[k]=k; pd[k]=1; A.clear(); B.clear(); //cout<<"solve "<<k<<endl;
	A.push_back((atom){k,1,g[k]});
	B.push_back((atom){k,0,0});
	for (int i=p[k];i;i=b[i].next){
		int j=b[i].point;
		if (pd[j]==0){
			dfs3(j,k,g[k]-b[i].w,-b[i].w,2,j);
			dfs4(j,k,-b[i].w,-b[i].w,1,j);
		}
	}
	sort(A.begin(),A.end(),compare);
	sort(B.begin(),B.end(),compare);
/*	cout<<"A"<<endl;
	for (int i=0;i<A.size();i++) cout<<A[i].where<<" "<<A[i].w<<" "<<A[i].f<<endl;
	cout<<"B"<<endl;
	for (int i=0;i<B.size();i++) cout<<B[i].where<<" "<<B[i].w<<" "<<B[i].f<<endl;*/
	int now=A.size()-1,where=0,f=-1e9,g=-1e9;
	for (int i=0;i<B.size();i++){
		while (now>=0&&A[now].f+B[i].f>=0){
			int k1=A[now].where;
			if (k1==where) f=max(f,A[now].w);
			else if (A[now].w>f){
				where=A[now].where; g=f; f=A[now].w;
			} else g=max(g,A[now].w);
			now--;
		}
		if (B[i].where==where) ans=max(ans,g+B[i].w); else ans=max(ans,f+B[i].w);
	}
	for (int i=p[k];i;i=b[i].next){
		int j=b[i].point;
		if (pd[j]==0) solve(j);
	}
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&g[i]);
	for (int i=1;i<n;i++){
		int k1,k2,k3; scanf("%d%d%d",&k1,&k2,&k3); add(k1,k2,k3);
	}
	ans=1;
	solve(1);
	printf("%d\n",ans);
	return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 15412
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge_base {
	int va, vb, cost;
};

struct edge {
	int to, cost;
};

struct state {
	int depth, current, bottom;
};

string to_string(const vector<int>& arr) {
	string res = "[";
	for (int i = 0; i < arr.size(); i++) {
		if (i != 0) {
			res += ", ";
		}
		res += to_string(arr[i]);
	}
	res += "]";
	return res;
}

int solve(int N, const vector<int>& A, const vector<edge_base>& E) {
	// step #1. make graph
	vector<vector<edge> > G(N);
	for (edge_base e : E) {
		G[e.va].push_back(edge{e.vb, e.cost});
		G[e.vb].push_back(edge{e.va, e.cost});
	}

	// step #2. find centroid
	int root = -1;
	vector<int> subsize(N, 1);
	auto find_centroid = [&](auto& self, int pos, int pre) -> void {
		bool flag = true;
		for (edge e : G[pos]) {
			if (e.to != pre) {
				self(self, e.to, pos);
				subsize[pos] += subsize[e.to];
				if (subsize[e.to] * 2 > N) {
					flag = false;
				}
			}
		}
		if (flag && subsize[pos] * 2 >= N) {
			root = pos;
		}
	};
	find_centroid(find_centroid, 0, -1);

	// step #3. build tree
	vector<int> comp(N, -1);
	vector<vector<edge> > child(N);
	auto build_tree = [&](auto& self, int pos, int pre) -> void {
		for (edge e : G[pos]) {
			if (e.to != pre) {
				comp[e.to] = comp[pos];
				child[pos].push_back(e);
				self(self, e.to, pos);
			}
		}
	};
	int K = G[root].size();
	child[root] = G[root];
	for (int i = 0; i < K; i++) {
		comp[G[root][i].to] = i;
		build_tree(build_tree, G[root][i].to, root);
	}

	// step #4. dynamic programming
	vector<state> dp1(N), dp2(N);
	auto dfs = [&](auto& self, int pos) -> void {
		for (edge e : child[pos]) {
			state u1 = dp1[pos];
			u1.depth += 1;
			u1.current += A[e.to] - e.cost;
			u1.bottom += A[e.to] - e.cost;
			u1.bottom = min(u1.bottom, 0);
			state u2 = dp2[pos];
			u2.depth += 1;
			u2.current += A[pos] - e.cost;
			u2.bottom = min(u2.bottom, u2.current);
			dp1[e.to] = u1;
			dp2[e.to] = u2;
			self(self, e.to);
		}
	};
	dp1[root] = state{0, 0, 0};
	dp2[root] = state{0, 0, 0};
	dfs(dfs, root);

	// step #5. calculate answer passing root
	int subanswer1 = -INF;
	vector<array<int, 3> > qs;
	for (int i = 0; i < N; i++) {
		if (dp1[i].bottom >= 0) {
			qs.push_back({dp1[i].current, 1, i});
		}
		qs.push_back({-dp2[i].bottom, 0, i});
	}
	sort(qs.begin(), qs.end());
	set<pair<int, int> > s;
	vector<int> compmax(K, -1);
	for (array<int, 3> v : qs) {
		if (v[1] == 0) {
			if (comp[v[2]] == -1 || compmax[comp[v[2]]] < dp2[v[2]].depth) {
				s.insert(make_pair(dp2[v[2]].depth, comp[v[2]]));
				if (comp[v[2]] != -1) {
					s.erase(make_pair(compmax[comp[v[2]]], comp[v[2]]));
					compmax[comp[v[2]]] = dp2[v[2]].depth;
				}
			}
		}
		else {
			set<pair<int, int> >::iterator it = s.end();
			if (it != s.begin()) {
				--it;
				if (it->second == -1 || it->second != comp[v[2]]) {
					subanswer1 = max(subanswer1, it->first + dp1[v[2]].depth + 1);
				}
				else if (it != s.begin()) {
					--it;
					subanswer1 = max(subanswer1, it->first + dp1[v[2]].depth + 1);
				}
			}
		}
	}

	// step #6. divide into subproblems
	vector<vector<int> > subcomp(K);
	for (int i = 0; i < N; i++) {
		if (i != root) {
			subcomp[comp[i]].push_back(i);
		}
	}
	vector<vector<int> > suba(K);
	vector<vector<edge_base> > sube(K);
	for (int i = 0; i < K; i++) {
		suba[i].resize(subcomp[i].size());
		for (int j = 0; j < subcomp[i].size(); j++) {
			suba[i][j] = A[subcomp[i][j]];
		}
	}
	for (int i = 0; i < N - 1; i++) {
		if (comp[E[i].va] == comp[E[i].vb]) {
			int id = comp[E[i].va];
			int nva = lower_bound(subcomp[id].begin(), subcomp[id].end(), E[i].va) - subcomp[id].begin();
			int nvb = lower_bound(subcomp[id].begin(), subcomp[id].end(), E[i].vb) - subcomp[id].begin();
			sube[id].push_back(edge_base{nva, nvb, E[i].cost});
		}
	}
	int subanswer2 = -INF;
	for (int i = 0; i < K; i++) {
		int res = solve(subcomp[i].size(), suba[i], sube[i]);
		subanswer2 = max(subanswer2, res);
	}

	return max(subanswer1, subanswer2);
}

int main() {
	int N;
	cin >> N;
	vector<int> A(N);
	for (int i = 0; i < N; i++) {
		cin >> A[i];
	}
	vector<edge_base> E(N - 1);
	for (int i = 0; i < N - 1; i++) {
		cin >> E[i].va >> E[i].vb >> E[i].cost;
		E[i].va -= 1;
		E[i].vb -= 1;
	}
	int ans = solve(N, A, E);
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 52592
final_rank: 8

code_snippet: #line 1 "e.cpp"
#line 1 "e.cpp"
/*	author:  Kite_kuma
	created: 2022.05.30 15:48:54 */

#line 2 "SPJ-Library/graph/graph.hpp"
#include <algorithm>
#include <cassert>
#include <deque>
#include <iostream>
#include <queue>
#include <tuple>
#include <vector>

#pragma region graph

template <class cost_type = long long>
class graph {
   public:
	struct edge {
	   public:
		int from, to;
		cost_type cost;
		int id;
		edge() = default;
		edge(int from_, int to_, cost_type cost_ = 1, int id_ = -1) : from(from_), to(to_), cost(cost_), id(id_) {}
		bool operator<(const edge &a) const { return cost < a.cost; }
		bool operator>(const edge &a) const { return cost > a.cost; }
		friend std::ostream &operator<<(std::ostream &s, const edge &a) {
			s << '(' << a.from << " -> " << a.to << "), cost: " << a.cost << ", id: " << a.id;
			return s;
		}
	};

   private:
	std::vector<std::vector<edge>> edges;
	int next_edge_id = 0;

   public:
	inline const std::vector<edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<edge> &operator[](int k) { return edges[k]; }

	int size() const { return int(edges.size()); }
	void resize(const int n) { edges.resize(n); }
	int edge_count() const { return next_edge_id; }

	friend std::ostream &operator<<(std::ostream &s, const graph<cost_type> &g) {
		for(const auto &adj : g.edges)
			for(const auto &ed : adj) s << ed << '\n';
		return s;
	}

	graph() = default;
	graph(int n) : edges(n) {}
	graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const cost_type INF = std::numeric_limits<cost_type>::max() / 3;

	void input(int e = -1, bool weight = false, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			std::cin >> u >> v;
			cost_type cost = 1;
			if(weight) std::cin >> cost;
			add_edge(u, v, cost, directed, idx);
		}
	}

	inline int add_edge(int u, int v, cost_type cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(u, v, cost, next_edge_id);
		if(!directed && u != v) edges[v].emplace_back(v, u, cost, next_edge_id);
		return next_edge_id++;
	}

	// Ο(V+E)
	std::vector<cost_type> bfs(int s) const {
		std::vector<cost_type> dist(size(), INF);
		std::queue<int> que;
		dist[s] = 0;
		que.push(s);
		while(!que.empty()) {
			int v = que.front();
			que.pop();
			for(auto &e : edges[v]) {
				if(dist[e.to] != INF) continue;
				dist[e.to] = dist[v] + e.cost;
				que.push(e.to);
			}
		}
		return dist;
	}

	// Ο(V+E)
	// constraint: cost of each edge is zero or x (>= 0)
	std::vector<cost_type> zero_one_bfs(int s) const {
		std::vector<cost_type> dist(size(), INF);
		std::deque<int> deq;
		dist[s] = 0;
		deq.push_back(s);
		while(!deq.empty()) {
			int v = deq.front();
			deq.pop_front();
			for(auto &e : edges[v]) {
				if(dist[e.to] > dist[v] + e.cost) {
					dist[e.to] = dist[v] + e.cost;
					e.cost ? deq.push_back(e.to) : deq.push_front(e.to);
				}
			}
		}
		return dist;
	}

	// Ο((E+V) lg E)
	// unreachable: INF
	std::vector<cost_type> dijkstra(int s) const {
		std::vector<cost_type> dist(size(), INF);
		const auto compare = [](const std::pair<cost_type, int> &a, const std::pair<cost_type, int> &b) { return a.first > b.first; };
		std::priority_queue<std::pair<cost_type, int>, std::vector<std::pair<cost_type, int>>, decltype(compare)> que{compare};
		dist[s] = 0;
		que.emplace(0, s);
		while(!que.empty()) {
			std::pair<cost_type, int> p = que.top();
			que.pop();
			int v = p.second;
			if(dist[v] < p.first) continue;
			for(auto &e : edges[v]) {
				if(dist[e.to] > dist[v] + e.cost) {
					dist[e.to] = dist[v] + e.cost;
					que.emplace(dist[e.to], e.to);
				}
			}
		}
		return dist;
	}

	// Ο(VE)
	// unreachable: INF
	// reachable via negative cycle: -INF
	std::vector<cost_type> bellman_ford(int s) const {
		int n = size();
		std::vector<cost_type> res(n, INF);
		res[s] = 0;
		for(int loop = 0; loop < n - 1; loop++) {
			for(int v = 0; v < n; v++) {
				if(res[v] == INF) continue;
				for(auto &e : edges[v]) {
					res[e.to] = std::min(res[e.to], res[v] + e.cost);
				}
			}
		}
		std::queue<int> que;
		std::vector<int> chk(n);
		for(int v = 0; v < n; v++) {
			if(res[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(res[e.to] > res[v] + e.cost and !chk[e.to]) {
					que.push(e.to);
					chk[e.to] = 1;
				}
			}
		}
		while(!que.empty()) {
			int now = que.front();
			que.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					que.push(e.to);
				}
			}
		}
		for(int i = 0; i < n; i++)
			if(chk[i]) res[i] = -INF;
		return res;
	}

	// Ο(V^3)
	std::vector<std::vector<cost_type>> warshall_floyd() const {
		const int n = size();
		std::vector<std::vector<cost_type>> dist(n, std::vector<cost_type>(n, INF));
		for(int i = 0; i < n; i++) dist[i][i] = 0;
		for(int i = 0; i < n; i++)
			for(auto &e : edges[i]) dist[i][e.to] = std::min(dist[i][e.to], e.cost);
		for(int k = 0; k < n; k++)
			for(int i = 0; i < n; i++) {
				if(dist[i][k] == INF) continue;
				for(int j = 0; j < n; j++) {
					if(dist[k][j] == INF) continue;
					dist[i][j] = std::min(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		return dist;
	}

	// Ο(V) (using DFS)
	// if a cycle exists, return {}
	std::vector<int> topological_sort() const {
		std::vector<int> res;
		std::vector<int> used(size(), 0);
		bool not_DAG = false;
		auto dfs = [&](auto self, int k) -> void {
			if(not_DAG) return;
			if(used[k]) {
				if(used[k] == 1) not_DAG = true;
				return;
			}
			used[k] = 1;
			for(auto &e : edges[k]) self(self, e.to);
			used[k] = 2;
			res.push_back(k);
		};
		for(int i = 0; i < size(); i++) dfs(dfs, i);
		if(not_DAG) return std::vector<int>{};
		std::reverse(res.begin(), res.end());
		return res;
	}

	bool is_dag() const { return !topological_sort().empty(); }

	// Ο(V)
	// array of the distance to the most distant vertex
	// constraint: the graph is a tree
	std::vector<cost_type> height() const {
		auto vec1 = bfs(0);
		int v1 = -1, v2 = -1;
		cost_type dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v1 = i;
		vec1 = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v2 = i;
		auto vec2 = bfs(v2);
		for(int i = 0; i < int(size()); i++) {
			if(vec1[i] < vec2[i]) vec1[i] = vec2[i];
		}
		return vec1;
	}

	// O(V+E)
	// vector<(int)(0 or 1)>
	// if it is not bipartite, return {}
	std::vector<int> bipartite_grouping() const {
		std::vector<int> colors(size(), -1);
		auto dfs = [&](auto self, int now, int col) -> bool {
			colors[now] = col;
			for(auto &e : edges[now]) {
				if(col == colors[e.to]) return false;
				if(colors[e.to] == -1 and !self(self, e.to, !col)) return false;
			}
			return true;
		};
		for(int i = 0; i < int(size()); i++)
			if(!colors[i] and !dfs(dfs, i, 0)) return std::vector<int>{};
		return colors;
	}

	bool is_bipartite() const { return !bipartite_grouping().empty(); }

	// Ο(V+E)
	// (v1, v2, diameter)
	std::tuple<int, int, cost_type> diameter() {
		std::vector<cost_type> dist = bfs(0);
		auto it = std::max_element(dist.begin(), dist.end());
		const int v = it - dist.begin();
		dist = bfs(v);
		it = std::max_element(dist.begin(), dist.end());
		return std::make_tuple(v, int(it - dist.begin()), *it);
	}

	// Ο(V+E)
	std::vector<int> subtree_size(const int root) {
		const int n = size();
		std::vector<int> ret(n, 1);
		auto dfs = [&](auto self, int now, int p = -1) -> void {
			for(const auto &e : (*this)[now]) {
				if(e.to == p) continue;
				self(self, e.to, now);
				ret[now] += ret[e.to];
			}
		};
		dfs(dfs, root);
		return ret;
	}

	// Ο(ElgE)
	cost_type prim() const {
		cost_type res = 0;
		std::priority_queue<edge, std::vector<edge>, std::greater<edge>> que;
		for(auto &e : edges[0]) que.push(e);
		std::vector<int> chk(size());
		chk[0] = 1;
		int cnt = 1;
		while(cnt < size()) {
			auto e = que.top();
			que.pop();
			if(chk[e.to]) continue;
			cnt++;
			res += e.cost;
			chk[e.to] = 1;
			for(auto &e2 : edges[e.to]) que.push(e2);
		}
		return res;
	}

	// Ο(ElgE)
	cost_type kruskal() const {
		std::vector<std::tuple<int, int, cost_type>> eds;
		for(const auto &adj : edges)
			for(const auto &ed : adj) eds.emplace_back(ed.from, ed.to, ed.cost);
		std::sort(eds.begin(), eds.end(), [](const std::tuple<int, int, cost_type> &a, const std::tuple<int, int, cost_type> &b) {
			return std::get<2>(a) < std::get<2>(b);
		});
		std::vector<int> uf_data(size(), -1);
		auto root = [&uf_data](auto self, int x) -> int {
			if(uf_data[x] < 0) return x;
			return uf_data[x] = self(self, uf_data[x]);
		};
		auto unite = [&uf_data, &root](int u, int v) -> bool {
			u = root(root, u), v = root(root, v);
			if(u == v) return false;
			if(uf_data[u] > uf_data[v]) std::swap(u, v);
			uf_data[u] += uf_data[v];
			uf_data[v] = u;
			return true;
		};
		cost_type ret = 0;
		for(auto &e : eds)
			if(unite(std::get<0>(e), std::get<1>(e))) ret += std::get<2>(e);
		return ret;
	}

	// O(V)
	std::vector<int> centroid() const {
		std::vector<int> centroid, sz(size());
		auto dfs = [&](auto self, int now, int per) -> void {
			sz[now] = 1;
			bool is_centroid = true;
			for(auto &e : edges[now]) {
				if(e.to != per) {
					self(self, e.to, now);
					sz[now] += sz[e.to];
					if(sz[e.to] > size() / 2) is_centroid = false;
				}
			}
			if(size() - sz[now] > size() / 2) is_centroid = false;
			if(is_centroid) centroid.push_back(now);
		};
		dfs(dfs, 0, -1);
		return centroid;
	}

	// O(V+E)
	// bridge: (s, t)  (s < t);
	std::pair<std::vector<std::pair<int, int>>, std::vector<int>> bridges_and_articulations() const {
		std::vector<int> order(size(), -1), low(size()), articulation;
		int order_next = 0;
		std::vector<std::pair<int, int>> bridge;
		auto dfs = [&](auto self, int now, int par = -1) -> void {
			low[now] = order[now] = order_next++;
			bool is_articulation = false;
			int cnt = 0;
			for(auto &ed : edges[now]) {
				int &nxt = ed.to;
				if(nxt == par) continue;
				if(order[nxt] == -1) {
					cnt++;
					self(self, nxt, now);
					if(order[now] < low[nxt]) bridge.push_back(std::minmax(now, nxt));
					if(order[now] <= low[nxt]) is_articulation = true;
					low[now] = std::min(low[now], low[nxt]);
				} else if(order[now] > order[nxt]) {
					low[now] = std::min(low[now], order[nxt]);
				}
			}
			if(par == -1 and cnt < 2) is_articulation = false;
			if(is_articulation) articulation.push_back(now);
			return;
		};
		for(int i = 0; i < (int)size(); i++)
			if(order[i] == -1) dfs(dfs, i);
		return std::make_pair(bridge, articulation);
	}

	// Ο(V+E)
	// directed graph from root to leaf
	graph root_to_leaf(int root = 0) const {
		graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(now, e.to, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// Ο(V+E)
	// directed graph from leaf to root
	graph leaf_to_root(int root = 0) const {
		graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(e.to, now, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// cost_type Chu_Liu_Edmonds(int root = 0) {}
};
#pragma endregion
#line 2 "SPJ-Library/graph/centroid_decomposition.hpp"

#include <functional>

// process(int root, const vector<int>& used_as_centroid) -> void
// used_as_centroid[vertex] := 1 if 'vertex' has been removed else 0
template <class edge_type>
void centroid_decomposition(const graph<edge_type> &g, const std::function<void(int, const std::vector<int> &)> &process) {
	std::vector<int> weight(g.size(), 0), used_as_centroid(g.size(), 0);

	auto calc_weight = [&](auto self, int now, int par) -> void {
		int &weight_now = (weight[now] = 1);
		for(const auto &ed : g[now]) {
			if(ed.to == par || used_as_centroid[ed.to]) continue;
			self(self, ed.to, now);
			weight_now += weight[ed.to];
		}
		return;
	};

	auto find_centroid = [&g, &calc_weight, &weight, &used_as_centroid](int now) -> int {
		calc_weight(calc_weight, now, -1);
		const int order_half = weight[now] >> 1;
		int par = -1;
		bool changed = true;
		while(std::exchange(changed, false)) {
			for(const auto &ed : g[now]) {
				if(ed.to != par && !used_as_centroid[ed.to] && weight[ed.to] > order_half) {
					par = now;
					now = ed.to;
					changed = true;
					break;
				}
			}
		}
		return now;
	};

	auto decomposite = [&g, &find_centroid, &used_as_centroid, &process](auto self, int now) -> void {
		now = find_centroid(now);
		process(now, used_as_centroid);
		used_as_centroid[now] = 1;
		for(const auto &ed : g[now])
			if(!used_as_centroid[ed.to]) self(self, ed.to);
		return;
	};

	for(int i = 0; i < g.size(); i++)
		if(!used_as_centroid[i]) decomposite(decomposite, i);
	return;
}
#line 5 "e.cpp"

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#line 7 "SPJ-Library/template/basic_func.hpp"

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 478 "e.cpp"

ll solve(int n) {
	VEC(ll, stand, n);
	graph<ll> g(n, -1, true, 0, 1);

	int ans = 1;

	vector<ll> up_tmp, dn_tmp;

	auto dfs = [&](int dist, int now, const vector<int> &used, auto self, int par, ll sum, ll minvalue, ll maxvalue) -> void {
		chmin(minvalue, sum);
		chmax(maxvalue, sum);
		sum += stand[now];
		chmax(maxvalue, sum);
		debug(dist, now, used, sum, minvalue, maxvalue);
		if((int)dn_tmp.size() <= dist) dn_tmp.resize(dist + 1, -INF);
		chmax(dn_tmp[dist], minvalue);
		if(sum - maxvalue >= 0 && sum >= 0LL) {
			if(int(up_tmp.size() <= dist)) up_tmp.resize(dist + 1, -INF);
			chmax(up_tmp[dist], sum);
		}
		foa(e, g[now]) {
			if(e.to == par || used[e.to]) continue;
			self(dist + 1, e.to, used, self, now, sum - e.cost, minvalue, maxvalue);
		}
		debug('f');
		return;
	};

	auto merge = [&](vll &a, vll &b, ll root) -> void {
		int as = int(a.size());
		int bs = int(b.size());
		int j = 0;
		drep(i, as) while(j < bs && b[j] + a[i] + root >= 0) {
			chmax(ans, i + j + 1);
			j++;
		}
		return;
	};

	auto process = [&](int root, const vector<int> &used) -> void {
		vll up(1, 0LL), dn(1, 0LL);
		foa(e, g[root]) {
			if(used[e.to]) continue;
			up_tmp.resize(1, 0LL);
			dn_tmp.resize(1, 0LL);
			dfs(1, e.to, used, dfs, root, -e.cost, INF, -INF);
			drep(i, int(up_tmp.size()) - 1) { chmax(up_tmp[i], up_tmp[i + 1]); }
			drep(i, int(dn_tmp.size()) - 1) { chmax(dn_tmp[i], dn_tmp[i + 1]); }

			merge(up, dn_tmp, stand[root]);
			merge(up_tmp, dn, stand[root]);

			debug(root, e.to);
			debug(up);
			debug(dn);
			debug(up_tmp);
			debug(dn_tmp);
			debug(stand[root]);
			// exit(0);
			if(ans == 2) {
			}

			if(up_tmp.size() > up.size()) up.resize(up_tmp.size(), -INF);
			if(dn_tmp.size() > dn.size()) dn.resize(dn_tmp.size(), -INF);
			rep(i, int(up_tmp.size())) { chmax(up[i], up_tmp[i]); }
			rep(i, int(dn_tmp.size())) { chmax(dn[i], dn_tmp[i]); }

			up_tmp.clear();
			dn_tmp.clear();
		}
		return;
	};

	centroid_decomposition(g, process);
	return (ans);
}

int main() {
	int n;
	while(cin >> n && n) {
		cout << solve(n) << '\n';
	}

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 24712
final_rank: 3

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

struct edge {
	int to, cost;
};
const int mn = 1 << 17;
vector<edge> G[mn];
int a[mn];
queue<vector<int>> q;
bool exi[mn];
int ans = 1;
void yaru(vector<int> v) {
	if (v.empty())return;
	//初期化
	for (int id : v)exi[id] = true;
	int g; int sz = v.size();

	function<int(int, int)> s_root = [&](int id, int fr)->int {
		int res = 1;
		int ma = 0;
		for (edge e: G[id]) {
			if (e.to == fr)continue;
			if (!exi[e.to])continue;
			int nex = s_root(e.to, id);
			ma = max(ma, nex);
			res += nex;
		}
		if (ma <= sz / 2 && sz - res <= sz / 2)g = id;
		return res;
	};
	s_root(v[0], -1);
	//ここまで初期化

	////重心を根としてなんかやる
	//function<void(int, int)> dfs = [&](int id, int fr) {
	//	if (!exi[id])return;
	//	for (int to : G[id]) {
	//		if (to == fr)continue;
	//		dfs(to, id);
	//	}
	//};
	//for (int to : G[g])dfs(to, g);




	//ここまで

	vector<vector<int>> chs;
	vector<int> nexs;
	function<void(int, int)> search_next = [&](int id, int fr) {
		if (!exi[id])return;
		nexs.push_back(id);
		for (edge e : G[id]) {
			if (e.to == fr)continue;
			search_next(e.to,id);
		}
	};
	//子を列挙する
	for (edge e : G[g]) {
		search_next(e.to, g);
		if (nexs.empty())continue;
		q.push(nexs);
		chs.push_back(nexs);
		nexs.clear();
	}

	//子達についてなんかやる
	vector<int> vd;
	
	function<void(int, int,int,int,int)> dfsto = [&](int id, int fr,int cur,int mi,int depth) {
		//cout << "? " << id <<" "<<fr<< "\n";
		if (mi >= 0)chmax(ans, depth + 1);
		while (vd.size() <= depth) {
			vd.push_back(2 * mod);
		}
		chmin(vd[depth], -mi);
		for (edge e : G[id]) {
			if (e.to == fr || !exi[e.to])continue;
			dfsto(e.to, id, cur + a[id] - e.cost, min(mi, cur + a[id] - e.cost), depth + 1);
		}
	};
	function<void(int, int, int, int, int)> dfsfrom = [&](int id, int fr, int cur, int mi, int depth) {
		if (mi >= 0)chmax(ans, depth + 1);
		if (mi >= 0) {
			int loc = upper_bound(all(vd), cur) - vd.begin();
			chmax(ans, loc + depth);
		}
		for (edge e : G[id]) {
			if (e.to == fr || !exi[e.to])continue;
			dfsfrom(e.to, id, cur + a[e.to] - e.cost, min(0, mi + a[e.to] - e.cost), depth + 1);
		}
	};
	vd = { 0 };
	for (edge e : G[g]) {
		if (exi[e.to]) {
			dfsfrom(e.to, g, a[e.to]-e.cost, min(0,a[e.to]-e.cost), 1);
			dfsto(e.to, g, a[g] - e.cost, min(0, a[g] - e.cost), 1);
		}
	}
	vd = { 0 };
	per(i, G[g].size()) {
		edge e = G[g][i];
		if (exi[e.to]) {
			dfsfrom(e.to, g, a[e.to] - e.cost, min(0, a[e.to] - e.cost), 1);
			dfsto(e.to, g, a[g] - e.cost, min(0, a[g] - e.cost), 1);
		}
	}

	for (int id : v)exi[id] = false;
}

void uoo(int n) {
	vector<int> ori(n); rep(i, n)ori[i] = i;
	q.push(ori);
	while (!q.empty()) {
		vector<int> v = q.front(); q.pop();
		yaru(v);
	}
}

void solve() {
	int n; cin >> n;
	rep(i, n)cin >> a[i];
	rep(i, n - 1) {
		int a, b, c; cin >> a >> b >> c; a--; b--;
		G[a].push_back({ b,c });
		G[b].push_back({ a,c });
	}
	uoo(n);
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 31444
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int maxn=1e6+10;
int n,g[maxn],st[maxn],to[maxn],nt[maxn],topt,w[maxn],ans,ma[maxn],cima[maxn],dp[maxn],a[maxn],p;
bool f[maxn];
void add(int x,int y,int z){to[++topt]=y; nt[topt]=st[x]; st[x]=topt; w[topt]=z;}
void dfs1(int x,int fa)
{
	dp[x]=0; int p=st[x];
	while (p)
	{
		if (to[p]!=fa) 
		{
			dfs1(to[p],x);
			if (ma[to[p]]>=ma[x])
			{
				cima[x]=ma[x];
				ma[x]=ma[to[p]];
			}
			else if (ma[to[p]]>cima[x]) cima[x]=ma[to[p]];
		}
		p=nt[p];
	}
	ma[x]++; cima[x]++;
}
void dfs2(int x,int fa,int d)
{
	dp[x]=max(d,ma[x]);
	int p=st[x];
	while (p)
	{
		if (to[p]!=fa)
		{
			int now=d+1;
			if (ma[x]==ma[to[p]]+1) now=max(now,cima[x]+1);
			else now=max(now,ma[x]+1);
			dfs2(to[p],x,now);
		}
		p=nt[p];
	}

}
void dfs3(int x,int fa,int now,long long G)
{
	if (G<0) return;
	G+=g[x]; ans=max(ans,now);
	int p=st[x];
	while (p)
	{
		if (to[p]!=fa) dfs3(to[p],x,now+1,G-w[p]);
		p=nt[p];
	}
}
void solve(int x)
{
	if (dp[a[x]]<=ans) return;
	dfs3(a[x],0,1,0);
	swap(a[x],a[p]); p--;
}
void solve1(int x)
{
	if (dp[x]<=ans) return;
	dfs3(x,0,1,0);
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&g[i]);
	for (int i=1;i<n;i++)
	{
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		add(x,y,z); add(y,x,z);
	}
	dfs1(1,0); dfs2(1,0,0);
	if (n<=10000)
	{
		for (int i=1;i<=n;i++) solve1(i);
	}
	else
	{
		for (int i=1;i<=n;i++) a[p++]=i;
		p--;
		while (clock()<1850 && p>-1) solve(rng()%(p+1));
	}
	printf("%d\n",ans);
return 0;
}
accuracy: 0.13924050632911392
time_ms: 10
memory_kb: 6424
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int maxn=1e6+10;
int n,g[maxn],st[maxn],to[maxn],nt[maxn],topt,w[maxn],ans,ma[maxn],cima[maxn],dp[maxn],a[maxn],p;
bool f[maxn];
void add(int x,int y,int z){to[++topt]=y; nt[topt]=st[x]; st[x]=topt; w[topt]=z;}
void dfs1(int x,int fa)
{
	dp[x]=0; int p=st[x];
	while (p)
	{
		if (to[p]!=fa) 
		{
			dfs1(to[p],x);
			if (ma[to[p]]>=ma[x])
			{
				cima[x]=ma[x];
				ma[x]=ma[to[p]];
			}
			else if (ma[to[p]]>cima[x]) cima[x]=ma[to[p]];
		}
		p=nt[p];
	}
	ma[x]++; cima[x]++;
}
void dfs2(int x,int fa,int d)
{
	dp[x]=max(d,ma[x]);
	int p=st[x];
	while (p)
	{
		if (to[p]!=fa)
		{
			int now=d+1;
			if (ma[x]==ma[to[p]]+1) now=max(now,cima[x]+1);
			else now=max(now,ma[x]+1);
			dfs2(to[p],x,now);
		}
		p=nt[p];
	}

}
void dfs3(int x,int fa,int now,long long G)
{
	if (G<0) return;
	G+=g[x]; ans=max(ans,now);
	int p=st[x];
	while (p)
	{
		if (to[p]!=fa) dfs3(to[p],x,now+1,G-w[p]);
		p=nt[p];
	}
}
void solve(int x)
{
	if (dp[a[x]]<=ans) return;
	dfs3(a[x],0,1,0);
	swap(a[x],a[p]); p--;
}
void solve1(int x)
{
	if (dp[x]<=ans) return;
	dfs3(x,0,1,0);
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&g[i]);
	for (int i=1;i<n;i++)
	{
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		add(x,y,z); add(y,x,z);
	}
	dfs1(1,0); dfs2(1,0,0);
	if (n<=1000)
	{
		for (int i=1;i<=n;i++) solve1(i);
	}
	else
	{
		for (int i=1;i<=n;i++) a[p++]=i;
		p--;
		while (clock()<1850 && p>-1) solve(rng()%(p+1));
	}
	printf("%d\n",ans);
return 0;
}
accuracy: 0.13924050632911392
time_ms: 10
memory_kb: 6380
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=2e9;
const int N=1e5+10;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(LL x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int n,ans;
struct edge{
	int r,v;
};
vector<edge> E[N];
int g[N];
void insert(int u,int v,int w){
	E[u].push_back(edge{v,w});
}
int mx,rt;
int sz[N];
bool vis[N];
void getrt(int x,int S,int fa){
	//cout<<x<<" "<<S<<" "<<fa<<endl;
    sz[x]=1;int son=0,y;
    for(int i=0;i<E[x].size();++i){
    	y=E[x][i].r;
    	if(vis[y]==0&&y!=fa){
            getrt(y,S,x);
            sz[x]+=sz[y];
            son=max(son,sz[y]);
        }
	}
    son=max(son,S-sz[x]);
    if(son<=mx){
        rt=x;
        mx=son;
    }
}
int dep[N],mxd[N];
int dis[N],oil[N];
void getdep(int x,int fa){
	int y;
	sz[x]=1;
	mxd[x]=dep[x];oil[x]=oil[fa]+g[x];
	for(int i=0;i<E[x].size();++i){
    	y=E[x][i].r;
    	if(vis[y]==0&&y!=fa){
    		dis[y]=dis[x]+E[x][i].v;
            dep[y]=dep[x]+1;
            getdep(y,x);
            sz[x]+=sz[y];
            mxd[x]=max(mxd[x],mxd[y]);
        }
	}
}
edge q[N];
bool cmp(edge x,edge y){
	return mxd[x.r]<mxd[y.r];
}
int pre[N],suf[N];
int PRE[N],SUF[N];
int wws[N],ned[N];
void cal(int x,int fa){
	int y;
	SUF[dep[x]]=min(SUF[dep[x]],wws[x]);
	if(ned[x]==0) PRE[dep[x]]=max(PRE[dep[x]],oil[x]-dis[x]);
	for(int i=0;i<E[x].size();++i){
    	y=E[x][i].r;
    	if(vis[y]==0&&y!=fa){
    		wws[y]=wws[x]+max(0,E[x][i].v-g[x]);
    		if(g[E[x][i].r]-E[x][i].v>=ned[x]) ned[E[x][i].r]=0;
    		else ned[E[x][i].r]=ned[x]+E[x][i].v-g[E[x][i].r];
    		cal(y,x);
        }
	}
}
void sol(int x,int S){
	mx=1e9;
	getrt(x,S,0);
	//cout<<rt<<endl;
	x=rt;
	dep[x]=0;dis[x]=0;
	getdep(x,0);
	int r=0;
	//cout<<rt<<endl;
	for(int i=0;i<E[x].size();++i){
		if(vis[E[x][i].r]==0) q[++r]=E[x][i];
	}
    if(r==0) return;
   // cout<<rt<<endl;
    sort(q+1,q+1+r,cmp);
    for(int i=0;i<=mxd[x];++i){
    	pre[i]=-INF;
    	suf[i]=INF;
	}
	pre[0]=g[x];
	suf[0]=0;
	for(int i=1;i<=r;++i){
		for(int j=0;j<=mxd[q[i].r];++j){
			PRE[j]=-INF;
			SUF[j]=INF;
		}
		ned[q[i].r]=max(0,q[i].v-g[q[i].r]);
		wws[q[i].r]=q[i].v;
		//if(q[i].v<=g[q[i].r]) PRE[1]=g[x]+g[q[i].r]-q[i].v;
		cal(q[i].r,x);
		for(int j=mxd[q[i].r];j>1;--j){
			SUF[j-1]=min(SUF[j],SUF[j-1]);
			PRE[j-1]=max(PRE[j],PRE[j-1]);
		}
		for(int j=1,k=mxd[q[i].r];j<=mxd[q[i].r];++j){
			while(k>0&&suf[k]>PRE[j]) --k;
			if(suf[k]<=PRE[j]) ans=max(ans,j+k+1);
		}
		for(int j=1,k=mxd[q[i].r];j<=mxd[q[i].r];++j){
			while(k>0&&pre[k]<SUF[j]) --k;
			if(SUF[j]<=pre[k]) ans=max(ans,j+k+1);
		}
		for(int j=mxd[q[i].r];j>=0;--j){
			suf[j]=min(suf[j],SUF[j]);
			pre[j]=max(pre[j],PRE[j]);
		}
		for(int j=mxd[q[i].r];j>=1;--j){
			suf[j-1]=min(suf[j],suf[j-1]);
			pre[j-1]=max(pre[j],pre[j-1]);
		}
		pre[0]=max(pre[1],pre[0]);
	}
	//cout<<ans<<endl;
	vis[x]=1;
	for(int i=0;i<E[x].size();++i){
		if(vis[E[x][i].r]==0) sol(E[x][i].r,sz[E[x][i].r]);
	}
}
int main(){
	scanf("%d",&n);ans=1;oil[0]=0;
	for(int i=1;i<=n;++i) scanf("%d",&g[i]);
	int u,v,w;
	for(int i=1;i<n;++i){
		scanf("%d%d%d",&u,&v,&w);
		insert(u,v,w);
		insert(v,u,w);
	}
	sol(1,n);
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.4050632911392405
time_ms: 50
memory_kb: 16172
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=1e9+10;
const int N=3e5+10;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(LL x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int n,ans;
struct edge{
	int r,v;
};
vector<edge> E[N];
int g[N];
void insert(int u,int v,int w){
	E[u].push_back(edge{v,w});
}
int mx,rt;
int sz[N];
bool vis[N];
void getrt(int x,int S,int fa){
	//cout<<x<<" "<<S<<" "<<fa<<endl;
    sz[x]=1;int son=0,y;
    for(int i=0;i<E[x].size();++i){
    	y=E[x][i].r;
    	if(vis[y]==0&&y!=fa){
            getrt(y,S,x);
            sz[x]+=sz[y];
            son=max(son,sz[y]);
        }
	}
    son=max(son,S-sz[x]);
    if(son<=mx){
        rt=x;
        mx=son;
    }
}
int dep[N],mxd[N];
int dis[N],oil[N];
void getdep(int x,int fa){
	int y;
	sz[x]=1;
	mxd[x]=dep[x];oil[x]=oil[fa]+g[x];
	for(int i=0;i<E[x].size();++i){
    	y=E[x][i].r;
    	if(vis[y]==0&&y!=fa){
    		dis[y]=dis[x]+E[x][i].v;
            dep[y]=dep[x]+1;
            getdep(y,x);
            sz[x]+=sz[y];
            mxd[x]=max(mxd[x],mxd[y]);
        }
	}
}
edge q[N];
bool cmp(edge x,edge y){
	return mxd[x.r]<mxd[y.r];
}
int pre[N],suf[N];
int PRE[N],SUF[N];
int wws[N],ned[N];
void cal(int x,int fa){
	int y;
	SUF[dep[x]]=min(SUF[dep[x]],wws[x]);
	if(ned[x]==0) PRE[dep[x]]=max(PRE[dep[x]],oil[x]-dis[x]);
	for(int i=0;i<E[x].size();++i){
    	y=E[x][i].r;
    	if(vis[y]==0&&y!=fa){
    		wws[y]=wws[x]+max(0,E[x][i].v-g[x]);
    		if(g[E[x][i].r]-E[x][i].v>=ned[x]) ned[E[x][i].r]=0;
    		else ned[E[x][i].r]=ned[x]+E[x][i].v-g[E[x][i].r];
    		cal(y,x);
        }
	}
}
void sol(int x,int S){
	mx=1e9;
	getrt(x,S,0);
	//cout<<rt<<endl;
	x=rt;
	dep[x]=0;dis[x]=0;
	getdep(x,0);
	int r=0;
	//cout<<rt<<endl;
	for(int i=0;i<E[x].size();++i){
		if(vis[E[x][i].r]==0) q[++r]=E[x][i];
	}
    if(r==0) return;
   // cout<<rt<<endl;
    sort(q+1,q+1+r,cmp);
    for(int i=0;i<=mxd[x];++i){
    	pre[i]=-INF;
    	suf[i]=INF;
	}
	pre[0]=g[x];
	suf[0]=0;
	for(int i=1;i<=r;++i){
		for(int j=0;j<=mxd[q[i].r];++j){
			PRE[j]=-INF;
			SUF[j]=INF;
		}
		ned[q[i].r]=max(0,q[i].v-g[q[i].r]);
		wws[q[i].r]=q[i].v;
		//if(q[i].v<=g[q[i].r]) PRE[1]=g[x]+g[q[i].r]-q[i].v;
		cal(q[i].r,x);
		for(int j=mxd[q[i].r];j>1;--j){
			SUF[j-1]=min(SUF[j],SUF[j-1]);
			PRE[j-1]=max(PRE[j],PRE[j-1]);
		}
		for(int j=1,k=mxd[q[i].r];j<=mxd[q[i].r];++j){
			while(k>0&&suf[k]>PRE[j]) --k;
			if(suf[k]<=PRE[j]) ans=max(ans,j+k+1);
		}
		for(int j=1,k=mxd[q[i].r];j<=mxd[q[i].r];++j){
			while(k>0&&pre[k]<SUF[j]) --k;
			if(SUF[j]<=pre[k]) ans=max(ans,j+k+1);
		}
		for(int j=mxd[q[i].r];j>=0;--j){
			suf[j]=min(suf[j],SUF[j]);
			pre[j]=max(pre[j],PRE[j]);
		}
		pre[0]=max(pre[1],pre[0]);
	}
	//cout<<ans<<endl;
	vis[x]=1;
	for(int i=0;i<E[x].size();++i){
		if(vis[E[x][i].r]==0) sol(E[x][i].r,sz[E[x][i].r]);
	}
}
int main(){
	scanf("%d",&n);ans=1;oil[0]=0;
	for(int i=1;i<=n;++i) scanf("%d",&g[i]);
	int u,v,w;
	for(int i=1;i<n;++i){
		scanf("%d%d%d",&u,&v,&w);
		insert(u,v,w);
		insert(v,u,w);
	}
	sol(1,n);
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.4050632911392405
time_ms: 50
memory_kb: 20776
final_rank: 16

code_snippet: #include <algorithm>
#include <set>
#include <limits>
#include <utility>
#include <iostream>
#include <type_traits>
#include <vector>
#include <cstdint>
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2790"

template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
template<typename F>
struct fixpoint : F
{
    fixpoint(F&& f) : F(std::forward<F>(f)) {}
    template<typename... Args>
    decltype(auto) operator()(Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); }
};
// template<typename F>
// inline decltype(auto) mfp(F&& f) { return fixpoint<F>{std::forward<F>(f)}; }
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }

template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return std::cout << "\n", 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
void outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class centroid
{
public:
    centroid(const base_tree<Edge>& tree) : cs(tree.size())
    {
        const std::size_t sz = tree.size();
        std::vector<std::size_t> sub(sz, 1);
        std::vector<bool> used(sz, false);
        auto size = [&, sz](auto&& self, const std::size_t s, const std::size_t p) -> std::size_t {
            sub[s] = 1;
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (to == p or used[to]) { continue; }
                sub[s] += self(self, to, s);
            }
            return sub[s];
        };
        auto search = [&, sz](auto&& self, const std::size_t s, const std::size_t p, const std::size_t tot) -> std::size_t {
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (p == to or used[to]) { continue; }
                if (sub[to] * 2 > tot) { return self(self, to, s, tot); }
            }
            return s;
        };
        auto build = [&, sz](auto&& self, const std::size_t s, const std::size_t pc) -> std::size_t {
            const std::size_t tot = size(size, s, sz), c = search(search, s, sz, tot);
            used[c] = true;
            if (pc != sz) { cs.add_edge(pc, c); }
            for (const auto& e : tree[c]) {
                const std::size_t to = e.to();
                if (not used[to]) { self(self, to, c); }
            }
            return c;
        };
        build(build, 0, sz);
    }
    const tree& centros() const { return cs; }

private:
    tree cs;
};
int main()
{
    auto N   = in<usize>();
    auto gas = in_v<ll>({N});
    cost_graph<ll> g(N);
    for (usize i = 0; i < N - 1; i++) {
        const auto a = in<usize>() - 1;
        const auto b = in<usize>() - 1;
        const auto d = in<ll>();
        g.add_edge(a, b, d, true);
    }
    const auto cg = centroid<edge<ll>>{g}.centros();
    usize centor  = 0;
    for (; centor < N; centor++) {
        if (cg.to(centor).empty()) { break; }
    }
    usize ans = 1;
    std::vector<bool> used(N, false);
    mfp([&](auto&& dfs, usize c) -> void {
        used[c]        = true;
        const usize cn = g[c].size();
        std::vector<std::vector<ll>> sub_ups(cn);
        std::vector<std::vector<ll>> sub_downs(cn);
        for (usize i = 0; i < cn; i++) {
            const auto& e = g[c][i];
            usize to      = e.to();
            if (used[to]) { continue; }
            ll cost = e.cost();
            sub_downs[i].push_back(0LL);
            sub_ups[i].push_back(0LL);
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c, ll min) -> void {
                if (sub_downs[i].size() <= d) { sub_downs[i].push_back(-inf_v<ll>); }
                chmax(sub_downs[i][d], min);
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    dfs(dfs, to, s, d + 1, c - cost + gas[s], std::min(min, c - cost + gas[s]));
                }
            })(to, c, 1, gas[c] - cost, std::min(gas[c] - cost, 0LL));
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c, ll min) -> void {
                if (sub_ups[i].size() <= d) { sub_ups[i].push_back(-inf_v<ll>); }
                if (min == 0) { chmax(sub_ups[i][d], c); }
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    const ll nmin = std::min(0LL, min - (cost - gas[to]));
                    dfs(dfs, to, s, d + 1, c - cost + gas[to], nmin);
                }
            })(to, c, 1, -cost + gas[to], std::min(0LL, -cost + gas[to]));
        }
        usize dmax = 0;
        for (usize i = 0; i < cn; i++) { chmax(dmax, sub_downs[i].size()); }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) {
                if (sub_downs[i][d] >= 0) { chmax(ans, d + 1); }
            }
            for (usize d = 1; d < sub_ups[i].size(); d++) {
                if (sub_ups[i][d] >= 0) { chmax(ans, d + 1); }
            }
        }
        for (usize i = 0; i < cn; i++) {
            for (int d = (int)sub_downs[i].size() - 1; d >= 1; d--) { chmax(sub_downs[i][d - 1], sub_downs[i][d]); }
        }
        std::vector<std::multiset<ll, std::greater<ll>>> sd(dmax);
        for (usize i = 0; i < cn; i++) {
            for (usize d = 0; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].erase(sd[d].find(sub_downs[i][d])); }
            for (usize d = 1; d < sub_ups[i].size(); d++) {
                const ll up = sub_ups[i][d];
                usize inf = 0, sup = dmax;
                while (sup - inf > 1) {
                    const usize mid                                      = (inf + sup) / 2;
                    const ll down                                        = (sd[mid].empty() ? -inf_v<ll> : *sd[mid].begin());
                    (up + down >= 0 and not sd[mid].empty() ? inf : sup) = mid;
                }
                if (inf > 0) { chmax(ans, d + inf + 1); }
            }
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (const usize nc : cg[c]) { dfs(dfs, nc); }
    })(centor);
    outln(ans);
    return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 53232
final_rank: 7

code_snippet: #include <algorithm>
#include <set>
#include <limits>
#include <utility>
#include <iostream>
#include <type_traits>
#include <vector>
#include <cstdint>
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2790"

template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
template<typename F>
struct fixpoint : F
{
    fixpoint(F&& f) : F(std::forward<F>(f)) {}
    template<typename... Args>
    decltype(auto) operator()(Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); }
};
// template<typename F>
// inline decltype(auto) mfp(F&& f) { return fixpoint<F>{std::forward<F>(f)}; }
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }

template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return std::cout << "\n", 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
void outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class centroid
{
public:
    centroid(const base_tree<Edge>& tree) : cs(tree.size())
    {
        const std::size_t sz = tree.size();
        std::vector<std::size_t> sub(sz, 1);
        std::vector<bool> used(sz, false);
        auto size = [&, sz](auto&& self, const std::size_t s, const std::size_t p) -> std::size_t {
            sub[s] = 1;
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (to == p or used[to]) { continue; }
                sub[s] += self(self, to, s);
            }
            return sub[s];
        };
        auto search = [&, sz](auto&& self, const std::size_t s, const std::size_t p, const std::size_t tot) -> std::size_t {
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (p == to or used[to]) { continue; }
                if (sub[to] * 2 > tot) { return self(self, to, s, tot); }
            }
            return s;
        };
        auto build = [&, sz](auto&& self, const std::size_t s, const std::size_t pc) -> std::size_t {
            const std::size_t tot = size(size, s, sz), c = search(search, s, sz, tot);
            used[c] = true;
            if (pc != sz) { cs.add_edge(pc, c); }
            for (const auto& e : tree[c]) {
                const std::size_t to = e.to();
                if (not used[to]) { self(self, to, c); }
            }
            return c;
        };
        build(build, 0, sz);
    }
    const tree& centros() const { return cs; }

private:
    tree cs;
};
int main()
{
    auto N   = in<usize>();
    auto gas = in_v<ll>({N});
    cost_graph<ll> g(N);
    for (usize i = 0; i < N - 1; i++) {
        const auto a = in<usize>() - 1;
        const auto b = in<usize>() - 1;
        const auto d = in<ll>();
        g.add_edge(a, b, d, true);
    }
    const auto cg = centroid<edge<ll>>{g}.centros();
    usize centor  = 0;
    for (; centor < N; centor++) {
        if (cg.to(centor).empty()) { break; }
    }
    usize ans = 1;
    std::vector<bool> used(N, false);
    mfp([&](auto&& dfs, usize c) -> void {
        used[c]        = true;
        const usize cn = g[c].size();
        std::vector<std::vector<ll>> sub_ups(cn);
        std::vector<std::vector<ll>> sub_downs(cn);
        for (usize i = 0; i < cn; i++) {
            const auto& e = g[c][i];
            usize to      = e.to();
            if (used[to]) { continue; }
            ll cost = e.cost();
            sub_downs[i].push_back(0LL);
            sub_ups[i].push_back(0LL);
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c, ll min) -> void {
                if (sub_downs[i].size() <= d) { sub_downs[i].push_back(-inf_v<ll>); }
                chmax(sub_downs[i][d], min);
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    chmin(min, c - cost + gas[s]);
                    dfs(dfs, to, s, d + 1, c - cost + gas[s], min);
                }
            })(to, c, 1, gas[c] - cost, std::min(gas[c] - cost, 0LL));
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c, ll min) -> void {
                if (sub_ups[i].size() <= d) { sub_ups[i].push_back(-inf_v<ll>); }
                if (min == 0) { chmax(sub_ups[i][d], c); }
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    min           = std::min(0LL, min - (cost - gas[to]));
                    dfs(dfs, to, s, d + 1, c - cost + gas[to], min);
                }
            })(to, c, 1, -cost + gas[to], std::min(0LL, -cost + gas[to]));
        }
        usize dmax = 0;
        for (usize i = 0; i < cn; i++) { chmax(dmax, sub_downs[i].size()); }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) {
                if (sub_downs[i][d] >= 0) { chmax(ans, d + 1); }
            }
            for (usize d = 1; d < sub_ups[i].size(); d++) {
                if (sub_ups[i][d] >= 0) { chmax(ans, d + 1); }
            }
        }
        for (usize i = 0; i < cn; i++) {
            for (int d = (int)sub_downs[i].size() - 1; d >= 1; d--) { chmax(sub_downs[i][d - 1], sub_downs[i][d]); }
        }
        std::vector<std::multiset<ll, std::greater<ll>>> sd(dmax);
        for (usize i = 0; i < cn; i++) {
            for (usize d = 0; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].erase(sd[d].find(sub_downs[i][d])); }
            for (usize d = 1; d < sub_ups[i].size(); d++) {
                const ll up = sub_ups[i][d];
                usize inf = 0, sup = dmax;
                while (sup - inf > 1) {
                    const usize mid                                      = (inf + sup) / 2;
                    const ll down                                        = (sd[mid].empty() ? -inf_v<ll> : *sd[mid].begin());
                    (up + down >= 0 and not sd[mid].empty() ? inf : sup) = mid;
                }
                if (inf > 0) { chmax(ans, d + inf + 1); }
            }
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (const usize nc : cg[c]) { dfs(dfs, nc); }
    })(centor);
    outln(ans);
    return 0;
}
accuracy: 0.6075949367088608
time_ms: 380
memory_kb: 53204
final_rank: 9

code_snippet: #include <algorithm>
#include <set>
#include <limits>
#include <utility>
#include <iostream>
#include <type_traits>
#include <vector>
#include <cstdint>
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2790"

template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
template<typename F>
struct fixpoint : F
{
    fixpoint(F&& f) : F(std::forward<F>(f)) {}
    template<typename... Args>
    decltype(auto) operator()(Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); }
};
// template<typename F>
// inline decltype(auto) mfp(F&& f) { return fixpoint<F>{std::forward<F>(f)}; }
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }

template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return std::cout << "\n", 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
void outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class centroid
{
public:
    centroid(const base_tree<Edge>& tree) : cs(tree.size())
    {
        const std::size_t sz = tree.size();
        std::vector<std::size_t> sub(sz, 1);
        std::vector<bool> used(sz, false);
        auto size = [&, sz](auto&& self, const std::size_t s, const std::size_t p) -> std::size_t {
            sub[s] = 1;
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (to == p or used[to]) { continue; }
                sub[s] += self(self, to, s);
            }
            return sub[s];
        };
        auto search = [&, sz](auto&& self, const std::size_t s, const std::size_t p, const std::size_t tot) -> std::size_t {
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (p == to or used[to]) { continue; }
                if (sub[to] * 2 > tot) { return self(self, to, s, tot); }
            }
            return s;
        };
        auto build = [&, sz](auto&& self, const std::size_t s, const std::size_t pc) -> std::size_t {
            const std::size_t tot = size(size, s, sz), c = search(search, s, sz, tot);
            used[c] = true;
            if (pc != sz) { cs.add_edge(pc, c); }
            for (const auto& e : tree[c]) {
                const std::size_t to = e.to();
                if (not used[to]) { self(self, to, c); }
            }
            return c;
        };
        build(build, 0, sz);
    }
    const tree& centros() const { return cs; }

private:
    tree cs;
};
int main()
{
    auto N   = in<usize>();
    auto gas = in_v<ll>({N});
    cost_graph<ll> g(N);
    for (usize i = 0; i < N - 1; i++) {
        const auto a = in<usize>() - 1;
        const auto b = in<usize>() - 1;
        const auto d = in<ll>();
        g.add_edge(a, b, d, true);
    }
    const auto cg = centroid<edge<ll>>{g}.centros();
    usize centor  = 0;
    for (; centor < N; centor++) {
        if (cg.to(centor).empty()) { break; }
    }
    usize ans = 1;
    std::vector<bool> used(N, false);
    mfp([&](auto&& dfs, usize c) -> void {
        used[c]        = true;
        const usize cn = g[c].size();
        std::vector<std::vector<ll>> sub_ups(cn);
        std::vector<std::vector<ll>> sub_downs(cn);
        for (usize i = 0; i < cn; i++) {
            const auto& e = g[c][i];
            usize to      = e.to();
            if (used[to]) { continue; }
            ll cost = e.cost();
            sub_downs[i].push_back(0LL);
            sub_ups[i].push_back(0LL);
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c, ll min) -> void {
                if (sub_downs[i].size() <= d) { sub_downs[i].push_back(c); }
                chmax(sub_downs[i][d], min);
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    chmin(min, c - cost + gas[s]);
                    dfs(dfs, to, s, d + 1, c - cost + gas[s], min);
                }
            })(to, c, 1, gas[c] - cost, std::min(gas[c] - cost, 0LL));
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c, ll min) -> void {
                if (sub_ups[i].size() <= d) { sub_ups[i].push_back(c); }
                if (min == 0) { chmax(sub_ups[i][d], c); }
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    chmin(min, std::min(0LL, min) - (cost - gas[to]));
                    dfs(dfs, to, s, d + 1, c - cost + gas[to], min);
                }
            })(to, c, 1, -cost + gas[to], std::min(0LL, -cost + gas[to]));
        }
        usize dmax = 0;
        for (usize i = 0; i < cn; i++) { chmax(dmax, sub_downs[i].size()); }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) {
                if (sub_downs[i][d] >= 0) { chmax(ans, d + 1); }
            }
            for (usize d = 1; d < sub_ups[i].size(); d++) {
                if (sub_ups[i][d] >= 0) { chmax(ans, d + 1); }
            }
        }
        for (usize i = 0; i < cn; i++) {
            for (int d = (int)sub_downs[i].size() - 1; d >= 1; d--) { chmax(sub_downs[i][d - 1], sub_downs[i][d]); }
        }
        std::vector<std::multiset<ll, std::greater<ll>>> sd(dmax);
        for (usize i = 0; i < cn; i++) {
            for (usize d = 0; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].erase(sd[d].find(sub_downs[i][d])); }
            for (usize d = 1; d < sub_ups[i].size(); d++) {
                const ll up = sub_ups[i][d];
                usize inf = 0, sup = dmax;
                while (sup - inf > 1) {
                    const usize mid                                      = (inf + sup) / 2;
                    const ll down                                        = (sd[mid].empty() ? -inf_v<ll> : *sd[mid].begin());
                    (up + down >= 0 and not sd[mid].empty() ? inf : sup) = mid;
                }
                if (inf > 0) { chmax(ans, d + inf + 1); }
            }
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (const usize nc : cg[c]) { dfs(dfs, nc); }
    })(centor);
    outln(ans);
    return 0;
}
accuracy: 0.4050632911392405
time_ms: 260
memory_kb: 49828
final_rank: 18

code_snippet: #include <algorithm>
#include <set>
#include <limits>
#include <utility>
#include <iostream>
#include <type_traits>
#include <vector>
#include <cstdint>
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2790"

template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
template<typename F>
struct fixpoint : F
{
    fixpoint(F&& f) : F(std::forward<F>(f)) {}
    template<typename... Args>
    decltype(auto) operator()(Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); }
};
// template<typename F>
// inline decltype(auto) mfp(F&& f) { return fixpoint<F>{std::forward<F>(f)}; }
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }

template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return std::cout << "\n", 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
void outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }
#    define SHOW(...) static_cast<void>(0)

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class centroid
{
public:
    centroid(const base_tree<Edge>& tree) : cs(tree.size())
    {
        const std::size_t sz = tree.size();
        std::vector<std::size_t> sub(sz, 1);
        std::vector<bool> used(sz, false);
        auto size = [&, sz](auto&& self, const std::size_t s, const std::size_t p) -> std::size_t {
            sub[s] = 1;
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (to == p or used[to]) { continue; }
                sub[s] += self(self, to, s);
            }
            return sub[s];
        };
        auto search = [&, sz](auto&& self, const std::size_t s, const std::size_t p, const std::size_t tot) -> std::size_t {
            for (const auto& e : tree[s]) {
                const std::size_t to = e.to();
                if (p == to or used[to]) { continue; }
                if (sub[to] * 2 > tot) { return self(self, to, s, tot); }
            }
            return s;
        };
        auto build = [&, sz](auto&& self, const std::size_t s, const std::size_t pc) -> std::size_t {
            const std::size_t tot = size(size, s, sz), c = search(search, s, sz, tot);
            used[c] = true;
            if (pc != sz) { cs.add_edge(pc, c); }
            for (const auto& e : tree[c]) {
                const std::size_t to = e.to();
                if (not used[to]) { self(self, to, c); }
            }
            return c;
        };
        build(build, 0, sz);
    }
    const tree& centros() const { return cs; }

private:
    tree cs;
};
int main()
{
    auto N   = in<usize>();
    auto gas = in_v<ll>({N});
    cost_graph<ll> g(N);
    for (usize i = 0; i < N - 1; i++) {
        const auto a = in<usize>() - 1;
        const auto b = in<usize>() - 1;
        const auto d = in<ll>();
        g.add_edge(a, b, d, true);
    }
    const auto cg = centroid<edge<ll>>{g}.centros();
    usize centor  = 0;
    for (; centor < N; centor++) {
        if (cg.to(centor).empty()) { break; }
    }
    usize ans = 1;
    std::vector<bool> used(N, false);
    mfp([&](auto&& dfs, usize c) -> void {
        used[c]        = true;
        const usize cn = g[c].size();
        std::vector<std::vector<ll>> sub_ups(cn);
        std::vector<std::vector<ll>> sub_downs(cn);
        for (usize i = 0; i < cn; i++) {
            const auto& e = g[c][i];
            usize to      = e.to();
            if (used[to]) { continue; }
            ll cost = e.cost();
            sub_downs[i].push_back(0LL);
            sub_ups[i].push_back(0LL);
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c) -> void {
                if (sub_downs[i].size() <= d) { sub_downs[i].push_back(c); }
                chmax(sub_downs[i][d], c);
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    dfs(dfs, to, s, d + 1, c - cost + gas[s]);
                }
            })(to, c, 1, gas[c] - cost);
            for (int d = (int)sub_downs[i].size() - 1; d >= 1; d--) { chmax(sub_downs[i][d - 1], sub_downs[i][d]); }
            mfp([&](auto&& dfs, usize s, usize p, usize d, ll c) -> void {
                if (sub_ups[i].size() <= d) { sub_ups[i].push_back(c); }
                chmax(sub_ups[i][d], c);
                for (const auto& e : g[s]) {
                    const usize to = e.to();
                    if (to == p or used[to]) { continue; }
                    const ll cost = e.cost();
                    dfs(dfs, to, s, d + 1, c - cost + gas[to]);
                }
            })(to, c, 1, -cost + gas[to]);
            for (int d = (int)sub_ups[i].size() - 1; d >= 1; d--) { chmax(sub_ups[i][d - 1], sub_ups[i][d]); }
        }
        SHOW(c, sub_downs, sub_ups);
        usize dmax = 0;
        for (usize i = 0; i < cn; i++) { chmax(dmax, sub_downs[i].size()); }
        SHOW(dmax);
        std::vector<std::multiset<ll, std::greater<ll>>> sd(dmax);
        for (usize i = 0; i < cn; i++) {
            for (usize d = 0; d < sub_downs[i].size(); d++) {
                if (sub_downs[i][d] >= 0) { chmax(ans, d + 1); }
            }
            for (usize d = 0; d < sub_ups[i].size(); d++) {
                if (sub_ups[i][d] >= 0) { chmax(ans, d + 1); }
            }
        }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 0; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (usize i = 0; i < cn; i++) {
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].erase(sd[d].find(sub_downs[i][d])); }
            SHOW(i, sd);
            for (usize d = 1; d < sub_downs[i].size(); d++) {
                const ll up = sub_ups[i][d];
                usize inf = 0, sup = dmax;
                while (sup - inf > 1) {
                    const usize mid              = (inf + sup) / 2;
                    const ll down                = (sd[mid].empty() ? -inf_v<ll> : *sd[mid].begin());
                    (up + down >= 0 ? inf : sup) = mid;
                }
                SHOW(i, d, inf, sup);
                if (inf > 0) { chmax(ans, d + inf + 1); }
            }
            for (usize d = 1; d < sub_downs[i].size(); d++) { sd[d].insert(sub_downs[i][d]); }
        }
        for (const usize nc : cg[c]) { dfs(dfs, nc); }
    })(centor);
    outln(ans);
    return 0;
}
accuracy: 0.4050632911392405
time_ms: 230
memory_kb: 49876
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100050

struct Edge{
    Edge(int arg_to,int arg_value,int arg_rev_value){
        to = arg_to;
        value = arg_value;
        rev_value = arg_rev_value;
    }
    int to,value,rev_value;
};

struct Info{

    int node_id,max_rest_size;
};


int *subtree_size;
bool *centroid;
vector<Edge> G[NUM];

void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}


Info search_centroid(int node_id,int parent,int total_size){

    Info ret,tmp;
    ret.max_rest_size = BIG_NUM;
    ret.node_id = -1;

    int sum = 1,maximum = 0;
    int next_node;

    for(int i = 0; i < G[node_id].size(); i++){

        next_node = G[node_id][i].to;
        if(centroid[next_node] == true || next_node == parent)continue;

        tmp = search_centroid(next_node,node_id,total_size);

        if(ret.max_rest_size > tmp.max_rest_size){

            ret.max_rest_size = tmp.max_rest_size;
            ret.node_id = tmp.node_id;
        }

        maximum = max(maximum,subtree_size[next_node]);
        sum += subtree_size[next_node];
    }
    maximum = max(maximum,total_size-sum);

    if(ret.max_rest_size > maximum){
        ret.max_rest_size = maximum;
        ret.node_id = node_id;
    }

    return ret;
}


int *DOWN;
int max_depth_DOWN;

void calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);
	max_depth_DOWN = max(max_depth_DOWN,depth);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		calc_DOWN(next_node,node_id,depth+1,next_minimum,next_sum);
	}
}


int ans;

void calc_UP(int node_id,int parent,int depth,int add,int sum,int maximum){

	int next_sum = sum+add;

	if(next_sum >= maximum){

		int L,R,mid;

		ans = max(ans,depth+1);

		L = 1,R = max_depth_DOWN,mid = (L+R)/2;

		while(L <= R){

			if(next_sum+DOWN[mid] >= 0){

				ans = max(ans,depth+mid+1);
				L = mid+1;

			}else{

				R = mid-1;
			}
			mid = (L+R)/2;
		}
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(centroid[next_node] == true || next_node == parent)continue;

		calc_UP(next_node,node_id,depth+1,G[node_id][i].rev_value,next_sum,max(maximum,next_sum));
	}
}


void solve_subproblem(int node_id){

    compute_subtree_size(node_id,-1);
    int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
    int size = subtree_size[node_id];

    centroid[center] = true;

    int next_node;

    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    for(int loop = 0; loop < 2; loop++){

        DOWN[0] = 0;
        for(int i = 1; i < size; i++){

            DOWN[i] = -BIG_NUM;
        }
        max_depth_DOWN = 0;

        for(int i = 0; i < G[center].size(); i++){

            next_node = G[center][i].to;

            if(centroid[next_node])continue;

            calc_UP(next_node,center,1,G[center][i].rev_value,0,0);
            calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value);
        }
        reverse(G[center].begin(),G[center].end());
    }
}

int main(){

	int V;

    scanf("%d",&V);

    int gasoline[V+5];
	subtree_size = new int[V+5];
	DOWN = new int[V+5];
	centroid = new bool[V+5];

    for(int i = 0; i < V; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < V-1; i++){

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist,gasoline[to]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist,gasoline[from]-dist));
    }


    for(int i = 0; i < V; i++){

        centroid[i] = false;
    }

    ans = 0;

    solve_subproblem(0);

    printf("%d\n",max(1,ans));

    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 20908
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100050

struct Edge{
    Edge(int arg_to,int arg_value,int arg_rev_value){
        to = arg_to;
        value = arg_value;
        rev_value = arg_rev_value;
    }
    int to,value,rev_value;
};

struct Info{

    int node_id,max_rest_size;
};


int *subtree_size;
bool *centroid; //その頂点が既に分割に用いられているか
vector<Edge> G[NUM];

void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}


Info search_centroid(int node_id,int parent,int total_size){

    Info ret,tmp;
    ret.max_rest_size = BIG_NUM;
    ret.node_id = -1;

    int sum = 1,maximum = 0;
    int next_node;

    for(int i = 0; i < G[node_id].size(); i++){ //子を走査

        next_node = G[node_id][i].to;
        if(centroid[next_node] == true || next_node == parent)continue;

        tmp = search_centroid(next_node,node_id,total_size);

        if(ret.max_rest_size > tmp.max_rest_size){

            ret.max_rest_size = tmp.max_rest_size;
            ret.node_id = tmp.node_id;
        }

        maximum = max(maximum,subtree_size[next_node]);
        sum += subtree_size[next_node];
    }
    maximum = max(maximum,total_size-sum);

    if(ret.max_rest_size > maximum){
        ret.max_rest_size = maximum;
        ret.node_id = node_id;
    }

    return ret;
}


int *DOWN;
int max_depth_DOWN;

void calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);
	max_depth_DOWN = max(max_depth_DOWN,depth);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		calc_DOWN(next_node,node_id,depth+1,next_minimum,next_sum);
	}
}


int ans;

//node_id以下の出発点で、最後にparentに辿り着く際の、最大のガソリン残量(★途中で負になる場合に注意★)
void calc_UP(int node_id,int parent,int depth,int add,int sum,int maximum){

	int next_sum = sum+add;

	if(next_sum >= maximum){

		int L,R,mid;

		ans = max(ans,depth+1); //上りのみの場合

		L = 1,R = max_depth_DOWN,mid = (L+R)/2;

		while(L <= R){

			if(next_sum+DOWN[mid] >= 0){

				ans = max(ans,depth+mid+1);
				L = mid+1;

			}else{

				R = mid-1;
			}
			mid = (L+R)/2;
		}
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(centroid[next_node] == true || next_node == parent)continue;

		calc_UP(next_node,node_id,depth+1,G[node_id][i].rev_value,next_sum,max(maximum,next_sum));
	}
}


void solve_subproblem(int node_id){

    //重心となる頂点centerを探す
    compute_subtree_size(node_id,-1); //部分木のサイズを計算するとともに、最大の深さを計算する
    int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
    int size = subtree_size[node_id]; //★再帰している間に値が書き換わるので退避★

    //printf("node_id:%d center:%d size[node]:%d\n",node_id,center,subtree_size[node_id]);

    centroid[center] = true;

    int next_node;

    //子の部分木を先に処理する
    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    //printf("subtree_size[%d]:%d\n",node_id,subtree_size[node_id]);

    for(int loop = 0; loop < 2; loop++){

        DOWN[0] = 0;
        for(int i = 1; i < size; i++){ //★サイズに注意★

            DOWN[i] = -BIG_NUM;
        }
        max_depth_DOWN = 0;

        for(int i = 0; i < G[center].size(); i++){ //右端を上りとして固定し、最長のパスを求める

            next_node = G[center][i].to;

            if(centroid[next_node])continue;

            //右端の上りを計算
            calc_UP(next_node,center,1,G[center][i].rev_value,0,0);
           //右端の下りを計算
            calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value);
        }
        reverse(G[center].begin(),G[center].end());
    }
}

int main(){

	int V;

    scanf("%d",&V);

    int gasoline[V+5];
	subtree_size = new int[V+5];
	DOWN = new int[V+5];
	centroid = new bool[V+5];

    for(int i = 0; i < V; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < V-1; i++){\

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist,gasoline[to]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist,gasoline[from]-dist));
    }


    for(int i = 0; i < V; i++){

        centroid[i] = false;
    }

    ans = 0;

    solve_subproblem(0);

    printf("%d\n",max(1,ans));

    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 20872
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100020

struct Edge{
    Edge(int arg_to,int arg_value,int arg_rev_value){
        to = arg_to;
        value = arg_value;
        rev_value = arg_rev_value;
    }
    int to,value,rev_value;
};


static int gasoline[NUM],subtree_size[NUM];
static bool centroid[NUM]; //その頂点が既に分割に用いられているか
static vector<Edge> G[NUM];

static void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}

vector<int> CENTROID;

static void search_centroid(int node_id,int parent,int total_size){

	bool FLG = true;

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;
		if(next_node == parent || centroid[next_node] == true)continue;
		search_centroid(next_node,node_id,total_size);

		if(subtree_size[next_node] > total_size/2){
			FLG = false;
			break;
		}
	}
	if(total_size-subtree_size[node_id] > total_size/2)return;
	if(FLG)CENTROID.push_back(node_id);
}


static int max_depth_DOWN,max_depth_UP;
static int DOWN[NUM];

static int V;
static int root,ans;

static int calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);
	max_depth_DOWN = max(max_depth_DOWN,depth);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		DOWN[depth] = max(DOWN[depth],calc_DOWN(next_node,node_id,depth+1,next_sum,next_minimum));
	}
	return DOWN[depth];
}


static void calc_UP(int node_id,int parent,int depth,int sum,int maximum){

	//sum += add; //親方向へのコストを足す
	//int next_sum = sum+add;
	int next_sum = sum;

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to == parent){
			next_sum += G[node_id][i].value;
			break;
		}
	}

	//総和の最大値を更新した場合[★これで途中で負になる区間があるかわかる。総和が減るなら、逆方向から歩けば負になる区間があるはず★]
	if(next_sum >= maximum){

		max_depth_UP = max(max_depth_UP,depth);

		int L,R,mid;

		 //最大値を計算
		ans = max(ans,depth+1); //上りだけの場合

		L = 1,R = max_depth_DOWN,mid = (L+R)/2;

		while(L <= R){

			if(next_sum+DOWN[mid] >= 0){ //ガソリンを空にせずにk+midだけ走れる

				ans = max(ans,depth+mid+1);
				L = mid+1;

			}else{

				R = mid-1;
			}
			mid = (L+R)/2;
		}
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		calc_UP(next_node,node_id,depth+1,next_sum,max(maximum,next_sum));
	}
}

static void solve_subproblem(int node_id){

    //重心となる頂点centerを探す
    compute_subtree_size(node_id,-1); //部分木のサイズを計算するとともに、最大の深さを計算する
    CENTROID.clear();
    //int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
	search_centroid(node_id,-1,subtree_size[node_id]);
    int center = CENTROID[0];

    centroid[center] = true;

    int next_node;

    //子の部分木を先に処理する
    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    for(int loop = 0; loop < 2; loop++){

        DOWN[0] = 0;
        for(int i = 1; i <= subtree_size[node_id]+5; i++){ //★サイズに注意★

            DOWN[i] = -BIG_NUM;
        }
        max_depth_DOWN = 0;

        for(int i = 0; i < G[center].size(); i++){ //右端を上りとして固定し、最長のパスを求める

            next_node = G[center][i].to;

            if(centroid[next_node])continue;

            calc_UP(next_node,center,1,0,0);

            //右端の下りを計算
            DOWN[0] = max(DOWN[0],calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value));
         }

         reverse(G[center].begin(),G[center].end());
    }

}

int main(){

    scanf("%d",&V);

    for(int i = 0; i < V; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < V-1; i++){

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist,gasoline[to]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist,gasoline[from]-dist));
    }


    root = 0;

    for(int i = 0; i < V; i++){

        centroid[i] = false;
    }

    ans = 0;

    solve_subproblem(root);

    printf("%d\n",max(1,ans));

    return 0;
}
accuracy: 0.4430379746835443
time_ms: 70
memory_kb: 13984
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100020

struct Edge{
    Edge(int arg_to,int arg_value,int arg_rev_value){
        to = arg_to;
        value = arg_value;
        rev_value = arg_rev_value;
    }
    int to,value,rev_value;
};


static int gasoline[NUM],subtree_size[NUM];
static bool centroid[NUM]; //その頂点が既に分割に用いられているか
static vector<Edge> G[NUM];

void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}

vector<int> CENTROID;

void search_centroid(int node_id,int parent,int total_size){

	bool FLG = true;

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;
		if(next_node == parent || centroid[next_node] == true)continue;
		search_centroid(next_node,node_id,total_size);

		if(subtree_size[next_node] > total_size/2){
			FLG = false;
			break;
		}
	}
	if(total_size-subtree_size[node_id] > total_size/2)return;
	if(FLG)CENTROID.push_back(node_id);
}


static int max_depth_DOWN,max_depth_UP;
static int DOWN[NUM];

static int V;
static int root,ans;

int calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);
	max_depth_DOWN = max(max_depth_DOWN,depth);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		DOWN[depth] = max(DOWN[depth],calc_DOWN(next_node,node_id,depth+1,next_sum,next_minimum));
	}
	return DOWN[depth];
}


void calc_UP(int node_id,int parent,int depth,int sum,int maximum){

	//sum += add; //親方向へのコストを足す
	//int next_sum = sum+add;
	int next_sum = sum;

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to == parent){
			next_sum += G[node_id][i].value;
			break;
		}
	}

	//総和の最大値を更新した場合[★これで途中で負になる区間があるかわかる。総和が減るなら、逆方向から歩けば負になる区間があるはず★]
	if(next_sum >= maximum){

		max_depth_UP = max(max_depth_UP,depth);

		int L,R,mid;

		 //最大値を計算
		ans = max(ans,depth+1); //上りだけの場合

		L = 1,R = max_depth_DOWN,mid = (L+R)/2;

		while(L <= R){

			if(next_sum+DOWN[mid] >= 0){ //ガソリンを空にせずにk+midだけ走れる

				ans = max(ans,depth+mid+1);
				L = mid+1;

			}else{

				R = mid-1;
			}
			mid = (L+R)/2;
		}
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		calc_UP(next_node,node_id,depth+1,next_sum,max(maximum,next_sum));
	}
}

void solve_subproblem(int node_id){

    //重心となる頂点centerを探す
    compute_subtree_size(node_id,-1); //部分木のサイズを計算するとともに、最大の深さを計算する
    CENTROID.clear();
    //int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
	search_centroid(node_id,-1,subtree_size[node_id]);
    int center = CENTROID[0];

    centroid[center] = true;

    int next_node;

    //子の部分木を先に処理する
    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    for(int loop = 0; loop < 2; loop++){

        DOWN[0] = 0;
        for(int i = 1; i <= subtree_size[node_id]+5; i++){ //★サイズに注意★

            DOWN[i] = -BIG_NUM;
        }
        max_depth_DOWN = 0;

        for(int i = 0; i < G[center].size(); i++){ //右端を上りとして固定し、最長のパスを求める

            next_node = G[center][i].to;

            if(centroid[next_node])continue;

            calc_UP(next_node,center,1,0,0);

            //右端の下りを計算
            DOWN[0] = max(DOWN[0],calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value));
         }

         reverse(G[center].begin(),G[center].end());
    }

}

int main(){

    scanf("%d",&V);

    for(int i = 0; i < V; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < V-1; i++){

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist,gasoline[to]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist,gasoline[from]-dist));
    }


    root = 0;

    for(int i = 0; i < V; i++){

        centroid[i] = false;
    }

    ans = 0;

    solve_subproblem(root);

    printf("%d\n",max(1,ans));

    return 0;
}
accuracy: 0.4430379746835443
time_ms: 70
memory_kb: 13992
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100020

struct Edge{
    Edge(int arg_to,int arg_value,int arg_rev_value){
        to = arg_to;
        value = arg_value;
        rev_value = arg_rev_value;
    }
    int to,value,rev_value;
};


int gasoline[NUM],subtree_size[NUM];
bool centroid[NUM]; //その頂点が既に分割に用いられているか
vector<Edge> G[NUM];

void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}

vector<int> CENTROID;

void search_centroid(int node_id,int parent,int total_size){

	bool FLG = true;

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;
		if(next_node == parent || centroid[next_node] == true)continue;
		search_centroid(next_node,node_id,total_size);

		if(subtree_size[next_node] > total_size/2){
			FLG = false;
			break;
		}
	}
	if(total_size-subtree_size[node_id] > total_size/2)return;
	if(FLG)CENTROID.push_back(node_id);
}


int max_depth_DOWN,max_depth_UP;
int DOWN[NUM];

int V;
int root,ans;

int calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);
	max_depth_DOWN = max(max_depth_DOWN,depth);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		DOWN[depth] = max(DOWN[depth],calc_DOWN(next_node,node_id,depth+1,next_sum,next_minimum));
	}
	return DOWN[depth];
}


void calc_UP(int node_id,int parent,int depth,int sum,int maximum){

	//sum += add; //親方向へのコストを足す
	//int next_sum = sum+add;
	int next_sum = sum;

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to == parent){
			next_sum += G[node_id][i].value;
			break;
		}
	}

	//総和の最大値を更新した場合[★これで途中で負になる区間があるかわかる。総和が減るなら、逆方向から歩けば負になる区間があるはず★]
	if(next_sum >= maximum){

		max_depth_UP = max(max_depth_UP,depth);

		int L,R,mid;

		 //最大値を計算
		ans = max(ans,depth+1); //上りだけの場合

		L = 1,R = max_depth_DOWN,mid = (L+R)/2;

		while(L <= R){

			if(next_sum+DOWN[mid] >= 0){ //ガソリンを空にせずにk+midだけ走れる

				ans = max(ans,depth+mid+1);
				L = mid+1;

			}else{

				R = mid-1;
			}
			mid = (L+R)/2;
		}
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		calc_UP(next_node,node_id,depth+1,next_sum,max(maximum,next_sum));
	}
}

void solve_subproblem(int node_id){

    //重心となる頂点centerを探す
    compute_subtree_size(node_id,-1); //部分木のサイズを計算するとともに、最大の深さを計算する
    CENTROID.clear();
    //int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
	search_centroid(node_id,-1,subtree_size[node_id]);
    int center = CENTROID[0];

    centroid[center] = true;

    int next_node;

    //子の部分木を先に処理する
    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    for(int loop = 0; loop < 2; loop++){

        DOWN[0] = 0;
        for(int i = 1; i <= subtree_size[node_id]+5; i++){ //★サイズに注意★

            DOWN[i] = -BIG_NUM;
        }
        max_depth_DOWN = 0;

        for(int i = 0; i < G[center].size(); i++){ //右端を上りとして固定し、最長のパスを求める

            next_node = G[center][i].to;

            if(centroid[next_node])continue;

            calc_UP(next_node,center,1,0,0);

            //右端の下りを計算
            DOWN[0] = max(DOWN[0],calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value));
         }

         reverse(G[center].begin(),G[center].end());
    }

}

int main(){

    scanf("%d",&V);

    for(int i = 0; i < V; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < V-1; i++){

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist,gasoline[to]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist,gasoline[from]-dist));
    }


    root = 0;

    for(int i = 0; i < V; i++){

        centroid[i] = false;
    }

    ans = 0;

    solve_subproblem(root);

    printf("%d\n",max(1,ans));

    return 0;
}
accuracy: 0.4430379746835443
time_ms: 70
memory_kb: 14028
final_rank: 12

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100020

struct Edge{
    Edge(int arg_to,int arg_value,int arg_rev_value){
        to = arg_to;
        value = arg_value;
        rev_value = arg_rev_value;
    }
    int to,value,rev_value;
};

int subtree_size[NUM];
bool centroid[NUM]; //その頂点が既に分割に用いられているか
vector<Edge> G[NUM];

void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}


vector<int> CENTROID;
void search_centroid(int node_id,int parent,int total_size){

	bool FLG = true;

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;
		if(next_node == parent || centroid[next_node] == true)continue;
		search_centroid(next_node,node_id,total_size);

		if(subtree_size[next_node] > total_size/2){
			FLG = false;
			break;
		}
	}
	if(total_size-subtree_size[node_id] > total_size/2)return;
	if(FLG)CENTROID.push_back(node_id);
}

int ans = 0;
int gasoline[NUM];


int DOWN[NUM];
int max_depth_DOWN,max_depth_UP;


int calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);
	max_depth_DOWN = max(max_depth_DOWN,depth);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		DOWN[depth] = max(DOWN[depth],calc_DOWN(next_node,node_id,depth+1,next_sum,next_minimum));
	}
	return DOWN[depth];
}


void calc_UP(int node_id,int parent,int depth,int sum,int maximum){

	//sum += add; //親方向へのコストを足す
	//int next_sum = sum+add;
	int next_sum = sum;

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to == parent){
			next_sum += G[node_id][i].value;
			break;
		}
	}

	//総和の最大値を更新した場合[★これで途中で負になる区間があるかわかる。総和が減るなら、逆方向から歩けば負になる区間があるはず★]
	if(next_sum >= maximum){

		max_depth_UP = max(max_depth_UP,depth);

		int L,R,mid;

		 //最大値を計算
		ans = max(ans,depth+1); //上りだけの場合

		L = 1,R = max_depth_DOWN,mid = (L+R)/2;

		while(L <= R){

			if(next_sum+DOWN[mid] >= 0){ //ガソリンを空にせずにk+midだけ走れる

				ans = max(ans,depth+mid+1);
				L = mid+1;

			}else{

				R = mid-1;
			}
			mid = (L+R)/2;
		}
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		calc_UP(next_node,node_id,depth+1,next_sum,max(maximum,next_sum));
	}
}

void solve_subproblem(int node_id){

    //重心となる頂点centerを探す
    compute_subtree_size(node_id,-1); //部分木のサイズを計算するとともに、最大の深さを計算する
    CENTROID.clear();
    //int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
	search_centroid(node_id,-1,subtree_size[node_id]);
    int center = CENTROID[0];

    centroid[center] = true;

    int next_node;

    //子の部分木を先に処理する
    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    for(int loop = 0; loop < 2; loop++){

        DOWN[0] = 0;
        for(int i = 1; i <= subtree_size[node_id]+5; i++){ //★サイズに注意★

            DOWN[i] = -BIG_NUM;
        }
        max_depth_DOWN = 0;

        for(int i = 0; i < G[center].size(); i++){ //右端を上りとして固定し、最長のパスを求める

            next_node = G[center][i].to;

            if(centroid[next_node])continue;

            calc_UP(next_node,center,1,0,0);

            //右端の下りを計算
            DOWN[0] = max(DOWN[0],calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value));
         }

         reverse(G[center].begin(),G[center].end());
    }

}

int main(){

	int N;

    scanf("%d",&N);

    for(int i = 0; i < N; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < N-1; i++){

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist,gasoline[to]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist,gasoline[from]-dist));
    }


    solve_subproblem(0);

    printf("%d\n",max(1,ans));

    return 0;
}
accuracy: 0.4430379746835443
time_ms: 70
memory_kb: 14056
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100020

struct Edge{
    Edge(int arg_to,int arg_value){
        to = arg_to;
        value = arg_value;
    }
    int to,value;
};

int subtree_size[NUM];
bool centroid[NUM]; //その頂点が既に分割に用いられているか
vector<Edge> G[NUM];
vector<int> CENTROID;

void compute_subtree_size(int node_id,int parent){

    subtree_size[node_id] = 1;

    for(int i = 0; i < G[node_id].size(); i++){

        if(centroid[G[node_id][i].to] == true || G[node_id][i].to == parent)continue;

        compute_subtree_size(G[node_id][i].to,node_id);

        subtree_size[node_id] += subtree_size[G[node_id][i].to];
    }
}


void search_centroid(int node_id,int parent,int total_size){

	bool FLG = true;

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;
		if(next_node == parent || centroid[next_node] == true)continue;
		search_centroid(next_node,node_id,total_size);

		if(subtree_size[next_node] > total_size/2){
			FLG = false;
		}
	}
	if(total_size-subtree_size[node_id] > total_size/2)FLG = false;
	if(FLG)CENTROID.push_back(node_id);
}


vector<int> DOWN;
int ans = 0;

int calc_DOWN(int node_id,int parent,int depth,int minimum,int sum){

	DOWN[depth] = max(DOWN[depth],minimum);

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		int next_sum = sum + G[node_id][i].value;
		int next_minimum = min(minimum,next_sum);

		DOWN[depth] = max(DOWN[depth],calc_DOWN(next_node,node_id,depth+1,next_sum,next_minimum));
	}
	return DOWN[depth];
}


void calc_UP(int node_id,int parent,int depth,int sum,int maximum){

	//sum += add; //親方向へのコストを足す
	//int next_sum = sum+add;
	int next_sum = sum;

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to == parent){
			next_sum += G[node_id][i].value;
			break;
		}
	}

	//総和の最大値を更新した場合[★これで途中で負になる区間があるかわかる。総和が減るなら、逆方向から歩けば負になる区間があるはず★]
	if(next_sum >= maximum){

		int L,R;

		 //最大値を計算
		ans = max(ans,depth); //上りだけの場合

		L = 0,R = DOWN.size();

		while(L+1 < R){
			int mid = (L+R)/2;
			if(next_sum+DOWN[mid] >= 0){ //ガソリンを空にせずにk+midだけ走れる

				L = mid;

			}else{

				R = mid;
			};
		}
		ans = max(ans,L+depth);
	}

	for(int i = 0; i < G[node_id].size(); i++){

		int next_node = G[node_id][i].to;

		if(next_node == parent || centroid[next_node] == true)continue;

		calc_UP(next_node,node_id,depth+1,next_sum,max(maximum,next_sum));
	}
}

void solve_subproblem(int node_id){

    //重心となる頂点centerを探す
    compute_subtree_size(node_id,-1); //部分木のサイズを計算するとともに、最大の深さを計算する
    CENTROID.clear();
    //int center = search_centroid(node_id,-1,subtree_size[node_id]).node_id;
	search_centroid(node_id,-1,subtree_size[node_id]);
    int center = CENTROID[0];
    int size = subtree_size[node_id];

    centroid[center] = true;

    int next_node;

    //子の部分木を先に処理する
    for(int i = 0; i < G[center].size(); i++){

        next_node = G[center][i].to;

        if(centroid[next_node] == true)continue;

        solve_subproblem(next_node);
    }

    centroid[center] = false;

    for(int loop = 0; loop < 2; loop++){

    	 DOWN.resize(size);

    	 for(int i = 0; i < size; i++){
    		 DOWN[i] = -(INT_MAX/3);
    	 }

        for(int i = 0; i < G[center].size(); i++){ //右端を上りとして固定し、最長のパスを求める

            next_node = G[center][i].to;

            if(centroid[next_node] == true)continue;

            calc_UP(next_node,center,1,0,0);

            //右端の下りを計算
            DOWN[0] = max(DOWN[0],calc_DOWN(next_node,center,1,G[center][i].value,G[center][i].value));
         }

         reverse(G[center].begin(),G[center].end());
    }

}

//WAになる原因が分らなかったので、DAyamaさんのコードを参考にさせてもらいました(ほぼ完全な写経)

int main(){

	int N;

    scanf("%d",&N);

    int gasoline[NUM];

    for(int i = 0; i < N; i++){

        scanf("%d",&gasoline[i]);
    }

    int from,to,dist;

    for(int i = 0; i < N-1; i++){

        scanf("%d %d %d",&from,&to,&dist);
        from--;
        to--;

        G[from].push_back(Edge(to,gasoline[from]-dist));
        G[to].push_back(Edge(from,gasoline[to]-dist));
    }

    solve_subproblem(0);

    printf("%d\n",ans+1);

    return 0;
}
accuracy: 0.4050632911392405
time_ms: 70
memory_kb: 14172
final_rank: 14