|
| 1 | +//http://codeforces.com/gym/100570/submission/21226425 |
| 2 | +#include <bits/stdc++.h> |
| 3 | +using namespace std; |
| 4 | +#define gc getchar_unlocked |
| 5 | +#define fo(i,n) for(i=0;i<n;i++) |
| 6 | +#define Fo(i,k,n) for(i=k;i<n;i++) |
| 7 | +#define ll long long |
| 8 | +#define si(x) scanf("%d",&x) |
| 9 | +#define sl(x) scanf("%I64d",&x) |
| 10 | +#define ss(s) scanf("%s",s) |
| 11 | +#define pb push_back |
| 12 | +#define mp make_pair |
| 13 | +#define F first |
| 14 | +#define S second |
| 15 | +#define all(x) x.begin(), x.end() |
| 16 | +#define clr(x) memset(x, 0, sizeof(x)) |
| 17 | +#define sortall(x) sort(all(x)) |
| 18 | +#define tr(it, a) for(auto it = a.begin(); it != a.end(); it++) |
| 19 | +#define PI 3.1415926535897932384626 |
| 20 | +typedef pair<int, int> pii; |
| 21 | +typedef pair<ll, ll> pll; |
| 22 | +typedef vector<int> vi; |
| 23 | +typedef vector<ll> vl; |
| 24 | +typedef vector<pii> vpii; |
| 25 | +typedef vector<pll> vpll; |
| 26 | +typedef vector<vi> vvi; |
| 27 | +typedef vector<vl> vvl; |
| 28 | +int mod ; |
| 29 | +const int N = 3e5; |
| 30 | +vi g[N], cg[N]; |
| 31 | +vl stree[N], contri[N], wt[N]; |
| 32 | +vi cur; |
| 33 | +int part; |
| 34 | +int gvis[N], c_par[N]; |
| 35 | +const int LG = 20; |
| 36 | +//LCA begins |
| 37 | +//1 based index |
| 38 | +int a[N], lvl[N], P[N][LG], sz[N]; |
| 39 | +ll D[N]; |
| 40 | +void predfs(int u, int par){ |
| 41 | + if (!par)lvl[u] = D[u] = 0; |
| 42 | + P[u][0] = par; |
| 43 | + int pos = -1; |
| 44 | + for(int v:g[u]){ |
| 45 | + int w = wt[u][++pos]; |
| 46 | + if (v == par) continue; |
| 47 | + lvl[v] = 1+lvl[u]; |
| 48 | + D[v] = w+D[u]; |
| 49 | + predfs(v, u); |
| 50 | + } |
| 51 | +} |
| 52 | +void prelca(int n){ |
| 53 | + int i, j; |
| 54 | + fo(i, LG) fo(j, n+1) P[j][i] = -1; |
| 55 | + lvl[0] = -1; |
| 56 | + predfs(1, 0); |
| 57 | + for(i=1; i<LG; i++){ |
| 58 | + Fo(j, 1, n+1) |
| 59 | + if (P[j][i-1] != -1) |
| 60 | + P[j][i] = P[P[j][i-1]][i-1]; |
| 61 | + } |
| 62 | +} |
| 63 | +int lca(int u, int v){ |
| 64 | + int i, lg; |
| 65 | + if (lvl[u] < lvl[v]) swap(u, v); |
| 66 | + for(lg = 0; (1<<lg) <= lvl[u]; lg++); |
| 67 | + lg--; |
| 68 | + for(i=lg; i>=0; i--){ |
| 69 | + if (lvl[u] - (1<<i) >= lvl[v]) |
| 70 | + u = P[u][i]; |
| 71 | + } |
| 72 | + if (u == v) return u; |
| 73 | + for(i=lg; i>=0; i--){ |
| 74 | + if (P[u][i] != -1 and P[u][i] != P[v][i]) |
| 75 | + u = P[u][i], v = P[v][i]; |
| 76 | + } |
| 77 | + return P[u][0]; |
| 78 | +} |
| 79 | + |
| 80 | +ll dis(int u, int v){ |
| 81 | + if (u == v) return 0; |
| 82 | + if (lvl[u] < lvl[v]) swap(u, v); |
| 83 | + int w = lca(u, v); |
| 84 | + return D[u] + D[v] - 2*D[w]; |
| 85 | +} |
| 86 | +//lca ends |
| 87 | +int tot = 0; |
| 88 | +void dfs2(int u, int par){ |
| 89 | + if (par == 0)tot = 0; |
| 90 | + sz[u] = 1; |
| 91 | + tot++; |
| 92 | + for(int v: g[u]){ |
| 93 | + if (gvis[v] or v == par) continue; |
| 94 | + dfs2(v, u); |
| 95 | + sz[u] += sz[v]; |
| 96 | + } |
| 97 | +} |
| 98 | +//centroid decomposition begins |
| 99 | +int centroid(int u, int par){ |
| 100 | + |
| 101 | + for(int v: g[u]){ |
| 102 | + if ( v == par or gvis[v]) continue; |
| 103 | + if (2*sz[v] > tot) return centroid(v, u); |
| 104 | + } |
| 105 | + return u; |
| 106 | +} |
| 107 | +void decompose(int u, int par){ |
| 108 | + dfs2(u, 0); |
| 109 | + int cen = centroid(u, 0); |
| 110 | + gvis[cen] = 1; |
| 111 | + if (par) c_par[cen] = par; |
| 112 | + for(int v: g[cen]) |
| 113 | + if (!gvis[v]) decompose(v, cen); |
| 114 | +} |
| 115 | +//build centroid tree |
| 116 | +void build_centroid_tree(int n){ |
| 117 | + int i; |
| 118 | + Fo(i, 1, n+1) if (c_par[i]) cg[c_par[i]].pb(i); |
| 119 | +} |
| 120 | +void calc_root(int u, int root){ |
| 121 | + stree[root].pb(dis(u, root)); |
| 122 | + for(int v: cg[u]) |
| 123 | + calc_root(v, root); |
| 124 | +} |
| 125 | +void calc_contri(int u, int root){ |
| 126 | + int par = c_par[root]; |
| 127 | + contri[root].pb(dis(u, par)); |
| 128 | + for(int v: cg[u]) |
| 129 | + calc_contri(v, root); |
| 130 | +} |
| 131 | +//traverse centroid tree |
| 132 | +void traverse_centroid_tree(int u, int par){ |
| 133 | + for(int v: cg[u]){ |
| 134 | + if (v == par) continue; |
| 135 | + traverse_centroid_tree(v, u); |
| 136 | + } |
| 137 | + calc_root(u, u); |
| 138 | + if (!par) |
| 139 | + return; |
| 140 | + calc_contri(u, u); |
| 141 | +} |
| 142 | +bool f(ll val, ll x){ |
| 143 | + return val >= x; |
| 144 | +} |
| 145 | +int bin(vl &a, ll val, int lo, int hi){ |
| 146 | + if (a.empty())return 0; |
| 147 | + if (val < 0)return 0; |
| 148 | + if (a[0] > val) return 0; |
| 149 | + if (lo == hi) return lo+1; |
| 150 | + if (lo+1 == hi){ |
| 151 | + if(f(val, a[hi]))return hi+1; |
| 152 | + return lo+1; |
| 153 | + } |
| 154 | + int mid = (lo+hi)/2; |
| 155 | + if(f(val, a[mid])) return bin(a, val, mid, hi); |
| 156 | + else return bin(a, val, lo, mid-1); |
| 157 | +} |
| 158 | +//# nodes u | dis(u,v) <= l |
| 159 | +int query(int v, ll l){ |
| 160 | + int ans = bin(stree[v], l, 0, (int)stree[v].size()-1); |
| 161 | + int u = v; |
| 162 | + int orig = v; |
| 163 | + v = c_par[v]; |
| 164 | + while(v){ |
| 165 | + ll y = dis(orig, v); |
| 166 | + ans += bin(stree[v], l-y, 0, (int)stree[v].size()-1); |
| 167 | + ans -= bin(contri[u], l-y, 0, (int)contri[u].size()-1); |
| 168 | + u = v; |
| 169 | + v = c_par[v]; |
| 170 | + } |
| 171 | + return ans; |
| 172 | +} |
| 173 | + |
| 174 | +//centroid decomposition ends |
| 175 | +int main() |
| 176 | +{ |
| 177 | + ios_base::sync_with_stdio(false); |
| 178 | + cin.tie(NULL); |
| 179 | + ll i,n,k,j, u, v, w, q; |
| 180 | + int t; |
| 181 | + cin>>n>>q; |
| 182 | + fo(i, n-1){ |
| 183 | + cin>>u>>v>>w; |
| 184 | + g[u].pb(v); |
| 185 | + g[v].pb(u); |
| 186 | + wt[v].pb(w); |
| 187 | + wt[u].pb(w); |
| 188 | + } |
| 189 | + prelca(n); |
| 190 | + decompose(1, 0); |
| 191 | + build_centroid_tree(n); |
| 192 | + Fo(i, 1, n+1) |
| 193 | + if (!c_par[i]) |
| 194 | + traverse_centroid_tree(i, 0); |
| 195 | + Fo(i, 1, n+1) sortall(contri[i]); |
| 196 | + Fo(i, 1, n+1) sortall(stree[i]); |
| 197 | + while(q--){ |
| 198 | + cin>>v>>w; |
| 199 | + cout<<query(v, w)<<endl; |
| 200 | + } |
| 201 | + return 0; |
| 202 | +} |
| 203 | + |
| 204 | +int mpow(int base, int exp) { |
| 205 | +base %= mod; |
| 206 | +int result = 1; |
| 207 | +while (exp > 0) { |
| 208 | +if (exp & 1) result = ((ll)result * base) % mod; |
| 209 | +base = ((ll)base * base) % mod; |
| 210 | +exp >>= 1; |
| 211 | +} |
| 212 | +return result; |
| 213 | +} |
0 commit comments