Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstdio>
- #include <vector>
- #include <algorithm>
- #define task ""
- using namespace std;
- using ll = long long;
- using ld = long double;
- const int N = 1e5 + 2;
- int n, q, ans[N], cnt[N];
- bool inused[N]; // Lưu xem cạnh i còn được dùng hay không, trong TH xóa bỏ để đi xuống cây con
- ll w[N], d[N], dep[N]; // Trọng số cạnh, trọng số truy vấn, độ sâu đỉnh
- vector<ll> res[N]; // Liệt kê tất cả các độ sâu ở trong nhánh (Dùng khi Prepare())
- vector<int> s[N]; // Các truy vấn của 1 nút
- vector<pair<int, int>> adj[N]; // Danh sách liên thuộc
- void Read()
- {
- cin >> n >> q;
- for (int i = 1; i < n; ++i)
- {
- int u, v;
- cin >> u >> v >> w[i];
- adj[u].push_back({v, i});
- adj[v].push_back({u, i});
- inused[i] = 1;
- }
- for (int i = 1; i <= q; ++i)
- {
- int v;
- cin >> v >> d[i];
- s[v].push_back(i);
- }
- }
- // Đếm số node trong 1 cây con
- void dfs_cnt(int v, int p)
- {
- cnt[v] = 1;
- for (auto i : adj[v])
- if (inused[i.second] && i.first != p)
- {
- dfs_cnt(i.first, v);
- cnt[v] += cnt[i.first];
- }
- }
- // Tìm centroid = tham
- int Find_centroid(const int &root)
- {
- int centroid = root;
- dfs_cnt(root, root);
- while (1)
- {
- int t, v(0);
- for (auto i : adj[centroid])
- if (inused[i.second] && cnt[i.first] < cnt[centroid])
- {
- if (v < cnt[i.first])
- {
- v = cnt[i.first];
- t = i.first;
- }
- }
- if (v <= cnt[root] / 2)
- return centroid;
- centroid = t;
- }
- }
- // Liệt kê hết tất cả các độ sâu ra (Chỉ có centroid và các con của centroid thôi nhé ạ
- void Prepare(int v, int p, const int &subtree, const int &root)
- {
- res[subtree].push_back(dep[v]);
- res[root].push_back(dep[v]);
- for (auto i : adj[v])
- if (inused[i.second] && i.first != p)
- {
- dep[i.first] = dep[v] + w[i.second];
- Prepare(i.first, v, subtree, root);
- }
- }
- // Đếm số thằng <= v
- int Know(vector<ll> &s, ll v)
- {
- return upper_bound(s.begin(), s.end(), v) - s.begin();
- }
- void GetAns(int v, int p, const int &subtree, const int &root)
- {
- // Số thằng <= d[i] (Là khoảng cách của truy vấn thứ i) - dep[v] trong toàn cây - nhánh này
- for (auto i : s[v])
- ans[i] += Know(res[root], d[i] - dep[v]) - Know(res[subtree], d[i] - dep[v]);
- for (auto i : adj[v])
- if (inused[i.second] && i.first != p)
- GetAns(i.first, v, subtree, root);
- }
- // Phân rã centroid
- void Recursive(int v)
- {
- int centroid = Find_centroid(v);
- dep[centroid] = 0;
- // Duyệt các cây con
- for (auto i : adj[centroid])
- if (inused[i.second])
- {
- dep[i.first] = w[i.second];
- Prepare(i.first, centroid, i.first, centroid);
- sort(res[i.first].begin(), res[i.first].end());
- }
- res[centroid].push_back(0);
- sort(res[centroid].begin(), res[centroid].end());
- // Update từng cây con một
- for (auto i : s[centroid])
- ans[i] += Know(res[centroid], d[i]);
- for (auto i : adj[centroid])
- if (inused[i.second])
- GetAns(i.first, centroid, i.first, centroid);
- for (auto i : adj[centroid])
- if (inused[i.second])
- {
- res[i.first].clear();
- inused[i.second] = 0;
- Recursive(i.first);
- }
- }
- void Solve()
- {
- Recursive(1);
- for (int i = 1; i <= q; ++i)
- cout << ans[i] << "\n";
- }
- int32_t main()
- {
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- if (fopen(task ".INP", "r"))
- {
- freopen(task ".INP", "r", stdin);
- freopen(task ".OUT", "w", stdout);
- }
- Read();
- Solve();
- }
Add Comment
Please, Sign In to add comment