Dang_Quan_10_Tin

dquery

Feb 2nd, 2021 (edited)
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.98 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <algorithm>
  5. #define task ""
  6. using namespace std;
  7. using ll = long long;
  8. using ld = long double;
  9.  
  10. const int N = 1e5 + 2;
  11. int n, q, ans[N], cnt[N];
  12. 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
  13. ll w[N], d[N], dep[N]; // Trọng số cạnh, trọng số truy vấn, độ sâu đỉnh
  14. vector<ll> res[N]; // Liệt kê tất cả các độ sâu ở trong nhánh (Dùng khi Prepare())
  15. vector<int> s[N]; // Các truy vấn của 1 nút
  16. vector<pair<int, int>> adj[N]; // Danh sách liên thuộc
  17.  
  18. void Read()
  19. {
  20.     cin >> n >> q;
  21.     for (int i = 1; i < n; ++i)
  22.     {
  23.         int u, v;
  24.         cin >> u >> v >> w[i];
  25.         adj[u].push_back({v, i});
  26.         adj[v].push_back({u, i});
  27.         inused[i] = 1;
  28.     }
  29.     for (int i = 1; i <= q; ++i)
  30.     {
  31.         int v;
  32.         cin >> v >> d[i];
  33.         s[v].push_back(i);
  34.     }
  35. }
  36.  
  37. // Đếm số node trong 1 cây con
  38.  
  39. void dfs_cnt(int v, int p)
  40. {
  41.     cnt[v] = 1;
  42.     for (auto i : adj[v])
  43.         if (inused[i.second] && i.first != p)
  44.         {
  45.             dfs_cnt(i.first, v);
  46.             cnt[v] += cnt[i.first];
  47.         }
  48. }
  49.  
  50. // Tìm centroid = tham
  51.  
  52. int Find_centroid(const int &root)
  53. {
  54.     int centroid = root;
  55.     dfs_cnt(root, root);
  56.     while (1)
  57.     {
  58.         int t, v(0);
  59.         for (auto i : adj[centroid])
  60.             if (inused[i.second] && cnt[i.first] < cnt[centroid])
  61.             {
  62.                 if (v < cnt[i.first])
  63.                 {
  64.                     v = cnt[i.first];
  65.                     t = i.first;
  66.                 }
  67.             }
  68.         if (v <= cnt[root] / 2)
  69.             return centroid;
  70.         centroid = t;
  71.     }
  72. }
  73.  
  74. // 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é ạ
  75.  
  76. void Prepare(int v, int p, const int &subtree, const int &root)
  77. {
  78.     res[subtree].push_back(dep[v]);
  79.     res[root].push_back(dep[v]);
  80.     for (auto i : adj[v])
  81.         if (inused[i.second] && i.first != p)
  82.         {
  83.             dep[i.first] = dep[v] + w[i.second];
  84.             Prepare(i.first, v, subtree, root);
  85.         }
  86. }
  87.  
  88. // Đếm số thằng <= v
  89.  
  90. int Know(vector<ll> &s, ll v)
  91. {
  92.     return upper_bound(s.begin(), s.end(), v) - s.begin();
  93. }
  94.  
  95. void GetAns(int v, int p, const int &subtree, const int &root)
  96. {
  97.     // 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
  98.     for (auto i : s[v])
  99.         ans[i] += Know(res[root], d[i] - dep[v]) - Know(res[subtree], d[i] - dep[v]);
  100.     for (auto i : adj[v])
  101.         if (inused[i.second] && i.first != p)
  102.             GetAns(i.first, v, subtree, root);
  103. }
  104.  
  105. // Phân rã centroid
  106.  
  107. void Recursive(int v)
  108. {
  109.     int centroid = Find_centroid(v);
  110.     dep[centroid] = 0;
  111.     // Duyệt các cây con
  112.     for (auto i : adj[centroid])
  113.         if (inused[i.second])
  114.         {
  115.             dep[i.first] = w[i.second];
  116.             Prepare(i.first, centroid, i.first, centroid);
  117.             sort(res[i.first].begin(), res[i.first].end());
  118.         }
  119.     res[centroid].push_back(0);
  120.     sort(res[centroid].begin(), res[centroid].end());
  121.     // Update từng cây con một
  122.     for (auto i : s[centroid])
  123.         ans[i] += Know(res[centroid], d[i]);
  124.     for (auto i : adj[centroid])
  125.         if (inused[i.second])
  126.             GetAns(i.first, centroid, i.first, centroid);
  127.     for (auto i : adj[centroid])
  128.         if (inused[i.second])
  129.         {
  130.             res[i.first].clear();
  131.             inused[i.second] = 0;
  132.             Recursive(i.first);
  133.         }
  134. }
  135.  
  136. void Solve()
  137. {
  138.     Recursive(1);
  139.     for (int i = 1; i <= q; ++i)
  140.         cout << ans[i] << "\n";
  141. }
  142.  
  143. int32_t main()
  144. {
  145.     ios_base::sync_with_stdio(0);
  146.     cin.tie(0);
  147.     cout.tie(0);
  148.     if (fopen(task ".INP", "r"))
  149.     {
  150.         freopen(task ".INP", "r", stdin);
  151.         freopen(task ".OUT", "w", stdout);
  152.     }
  153.     Read();
  154.     Solve();
  155. }
  156.  
Add Comment
Please, Sign In to add comment