1 | #include<bits/stdc++.h> |
2 | using namespace std; |
3 | #define ll long long |
4 | #define all(d) d.begin(),d.end() |
5 | #define test int t;cin>>t;while(t--) |
6 | #define ones(n) __builtin_popcount(n) |
7 | #define last(n) ____builtin_clz(len) |
8 | const int dx8[8] = {1, 0, -1, 0,-1,-1,1,1}; |
9 | const int dy8[8] = {0, 1, 0, -1, -1, 1, -1, 1}; |
10 | int dx[] = {+0, +0, +1, -1}; |
11 | int dy[] = {+1, -1, +0, +0}; |
12 | char di[]={'R','L','D','U'}; |
13 | void JOO() { |
14 | ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); |
15 | #ifndef ONLINE_JUDGE |
16 | freopen("input.txt", "r", stdin); |
17 | freopen("output.txt", "w", stdout); |
18 | #endif |
19 | } |
20 | const int N=4e5+5,M=1e3,LOG=20,inf=0x3f3f3f3f; |
21 | int MOD=1e9+7; |
22 | ll infLL=0x3f3f3f3f3f3f3f3f; |
23 | struct item |
24 | { |
25 | vector<int>v; |
26 | }; |
27 | struct segTree |
28 | { |
29 | int sz=1; |
30 | vector<item>values; |
31 | item NEUTRAl_ElEMENT= {{}}; |
32 | item merge(item a,item b) |
33 | { |
34 | item ret; |
35 | ret.v.resize(a.v.size()+b.v.size()); |
36 | ::merge(all(a.v),all(b.v),ret.v.begin()); |
37 | return ret; |
38 | } |
39 | segTree(int n) |
40 | { |
41 | while (sz<n) |
42 | sz*=2; |
43 | values.resize(2*sz, NEUTRAl_ElEMENT); |
44 | } |
45 | void set(int i,int v,int x,int lx,int rx) |
46 | { |
47 | if(rx-lx==1) |
48 | { |
49 | if(values[x].v.empty()) |
50 | values[x].v.push_back(v); |
51 | else |
52 | values[x].v.pop_back(); |
53 | return; |
54 | } |
55 | int m=(lx+rx)/2; |
56 | if(i<m) |
57 | { |
58 | set(i,v,2*x+1, lx, m); |
59 | } |
60 | else |
61 | { |
62 | set(i,v,2*x+2,m, rx); |
63 | } |
64 | values[x]=merge(values[2*x+1],values[2*x+2]); |
65 | } |
66 | void set(int x,int v) |
67 | { |
68 | set(x,v,0,0,sz); |
69 | } |
70 | item query(int l,int r,int i,int lx,int rx) |
71 | { |
72 | if(rx <= l||r <= lx) |
73 | return NEUTRAl_ElEMENT; |
74 | if(lx >= l&&rx <= r) |
75 | { |
76 | return values[i]; |
77 | } |
78 | int m=(lx+rx)/2; |
79 | return merge(query(l,r,2*i+1,lx,m),query(l,r,2*i+2,m,rx)); |
80 | } |
81 | ll query(int l,int r,int k) |
82 | { |
83 | item ret=query(l,r+1,0,0,sz); |
84 | ll sz=ret.v.size(); |
85 | return sz-(upper_bound(all(ret.v),k)-ret.v.begin()); |
86 | } |
87 | }; |
88 | int n, q, anc[N][30], depth[N]; |
89 | vector <int> child[N]; |
90 | void dfs(int u,int p, int d) { |
91 | if(p!=-1) |
92 | anc[u][0]=p; |
93 | depth[u] = d; |
94 | for(int v : child[u]) { |
95 | if(v!=p) |
96 | dfs(v,u, d + 1); |
97 | } |
98 | } |
99 | void build() { |
100 | for(int k = 1; k < 30; k++) { |
101 | for(int i = 1; i <= n; i++) { |
102 | anc[i][k] = anc[anc[i][k - 1]][k - 1]; |
103 | } |
104 | } |
105 | } |
106 | int lift(int x, int k) { |
107 | for(int bit = 0; bit < 30; bit++) { |
108 | if((1 << bit & k)) { |
109 | x = anc[x][bit]; |
110 | } |
111 | } |
112 | return x; |
113 | } |
114 | int lca(int u, int v) { |
115 | if(depth[u] < depth[v]) |
116 | swap(u, v); |
117 | u = lift(u, depth[u] - depth[v]); |
118 | if(u == v) |
119 | return u; |
120 | for(int bit = 29; bit >= 0; bit--) { |
121 | if(anc[u][bit] != anc[v][bit]) { |
122 | u = anc[u][bit]; |
123 | v = anc[v][bit]; |
124 | } |
125 | } |
126 | return anc[u][0]; |
127 | } |
128 | vector<pair<int,int>>queries[N]; |
129 | ll ans[N],val[N],timer,in[N],arr[N]; |
130 | void calc(int u,int p,segTree &seg) |
131 | { |
132 | in[u]=timer++; |
133 | seg.set(in[u],arr[u]); |
134 | for(auto[l,idx]:queries[u]) |
135 | { |
136 | ans[idx]+=seg.query(in[l],in[u],val[idx]); |
137 | } |
138 | for(int v:child[u]) |
139 | { |
140 | if(v==p) |
141 | continue; |
142 | calc(v,u,seg); |
143 | } |
144 | seg.set(in[u],arr[u]); |
145 | } |
146 | void solve() |
147 | { |
148 | cin>>n>>q; |
149 | timer=0; |
150 | segTree seg(n); |
151 | for (int i = 0; i < n; ++i) { |
152 | child[i].clear(); |
153 | queries[i].clear(); |
154 | } |
155 | for (int i = 0; i < q; ++i) { |
156 | ans[i]=0; |
157 | } |
158 | for (int i = 0; i < n; ++i) { |
159 | cin>>arr[i]; |
160 | } |
161 | for (int i = 0; i < n-1; ++i) { |
162 | int u,v;cin>>u>>v; |
163 | u--,v--; |
164 | child[u].push_back(v); |
165 | child[v].push_back(u); |
166 | } |
167 | dfs(0,-1,0); |
168 | build(); |
169 | for (int i = 0; i <q; ++i) |
170 | { |
171 | int u,v,k; |
172 | cin>>u>>v>>k; |
173 | u--,v--; |
174 | val[i]=k; |
175 | int l=lca(u,v); |
176 | if(l!=u) |
177 | queries[u].push_back({l,i}); |
178 | if(l!=v) |
179 | queries[v].push_back({l,i}); |
180 | if(l!=v&&l!=u) |
181 | { |
182 | ans[i]-=bool(arr[l]>k); |
183 | } |
184 | if(l==u&&l==v) |
185 | ans[i]=(arr[l]>k); |
186 | } |
187 | calc(0,-1,seg); |
188 | for (int i = 0; i < q; ++i) { |
189 | cout<<ans[i]<<'\n'; |
190 | } |
191 | } |
192 | signed main() { |
193 | JOO(); |
194 | |
195 | test |
196 | { |
197 | |
198 | solve(); |
199 | } |
200 | } |