Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #include "bits/stdc++.h"
- using namespace std;
- #define all(a) a.begin(), a.end()
- #define int long long
- mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
- typedef long double ld;
- const int c = 330;
- const int N = 1e5 + 1;
- const int LG = 20;
- int up[LG][N] = {}, d[N] = {};
- struct Set_sqrt {
- int n;
- vector<int> cnt, st, sq;
- Set_sqrt(int _n) : n(_n) {
- cnt.resize(_n + 1); st.resize(_n + 1); sq.resize(c + 1);
- }
- void insert(int x) {
- if (x > n) return;
- cnt[x]++;
- if (cnt[x] == 1) {
- sq[x / c]++;
- st[x] = 1;
- }
- }
- void erase(int x) {
- if (x > n) return;
- cnt[x]--;
- if (cnt[x] == 0) {
- sq[x / c]--;
- st[x] = 0;
- }
- }
- int get_mex() {
- int it = 0;
- while (sq[it] == c) { it++; }
- int res = it * c;
- while (st[res] == 1) { res++; }
- return res;
- }
- };
- struct Edge {
- int u, w, ind;
- Edge(int _u, int _w, int _i) : u(_u), w(_w), ind(_i) {}
- };
- struct Query {
- int l, r, ind;
- Query(int _l, int _r, int _i) : l(_l), r(_r), ind(_i) {};
- bool operator<(const Query& other) {
- if (l / c == other.l / c) {
- if ((l / c) & 1) {
- return r > other.r;
- }
- return r < other.r;
- }
- return l < other.l;
- }
- };
- int t = 0;
- vector<pair<int, int>> euler;
- vector<int> tin, tout;
- vector<vector<Edge>> gr;
- vector<int> ed;
- void dfs(int v, int p) {
- for (int lvl = 1; lvl < LG; lvl++) {
- up[lvl][v] = up[lvl - 1][up[lvl - 1][v]];
- }
- for (auto&& [u, w, ind] : gr[v]) {
- if (u != p) {
- d[u] = d[v] + 1;
- up[0][u] = v;
- euler.push_back({ w, ind });
- tin[ind] = t++;
- ed[u] = ind;
- dfs(u, v);
- euler.push_back({ w, ind });
- tout[ind] = t++;
- }
- }
- }
- int lca(int a, int b) {
- for (int i = LG - 1; i >= 0; i--) {
- if (d[up[i][a]] > d[b]) {
- a = up[i][a];
- }
- }
- if (up[0][a] == b) { return a; }
- a = up[0][a];
- for (int i = LG - 1; i >= 0; i--) {
- if (up[i][a] != up[i][b]) {
- a = up[i][a]; b = up[i][b];
- }
- }
- return up[0][a];
- }
- signed main() {
- #ifdef _DEBUG
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- int n, m; cin >> n >> m;
- gr.resize(n), tin.resize(n); tout.resize(n); ed.resize(n);
- for (int i = 0; i < n - 1; i++) {
- int u, v, w;
- cin >> u >> v >> w;
- u--, v--;
- gr[u].push_back(Edge(v, w, i));
- gr[v].push_back(Edge(u, w, i));
- }
- d[0] = up[0][0] = 0;
- dfs(0, 0);
- vector<Query> q;
- auto get_query = [&](int u, int v, int& l, int& r) {
- if (d[u] > d[v]) {
- swap(u, v);
- }
- int lc = lca(v, u);
- if (up[0][lc] == u) {
- u = ed[lc];
- v = ed[v];
- }
- else {
- u = ed[u];
- v = ed[v];
- }
- if (tin[u] > tin[v]) {
- swap(u, v);
- }
- if (tout[u] < tin[v]) l = tout[u], r = tin[v];
- else l = tin[u], r = tin[v];
- };
- for (int i = 0; i < m; i++) {
- int u, v;
- cin >> u >> v;
- u--, v--;
- int l, r; get_query(u, v, l, r);
- q.push_back(Query(l, r, i));
- }
- vector<int> ans(m), count_in(n, 0);
- Set_sqrt U(n);
- sort(all(q));
- auto recalc = [&](pair<int, int>& x) {
- if (!count_in[x.second]) { U.insert(x.first); }
- else { U.erase(x.first); }
- count_in[x.second] ^= 1;
- };
- int l = 0, r = -1;
- for (const Query& i : q) {
- while (l > i.l) { recalc(euler[--l]); }
- while (r < i.r) { recalc(euler[++r]); }
- while (l < i.l) { recalc(euler[l++]); }
- while (r > i.r) { recalc(euler[r--]); }
- ans[i.ind] = U.get_mex();
- }
- for (int i = 0; i < m; i++) {
- cout << ans[i] << '\n';
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement