제출 #554969

#제출 시각아이디문제언어결과실행 시간메모리
554969Sweezy다리 (APIO19_bridges)C++17
100 / 100
2420 ms31000 KiB
#include <bits/stdc++.h>

using namespace std;
#define int long long

struct DSU {
  int n;
  vector<int> p, s;
  DSU(int n): n(n), p(n), s(n) {
    iota(p.begin(), p.end(), 0);
    fill(s.begin(), s.end(), 1);
  };

  int get(int v) {
    return (p[v] == v ? v : p[v] = get(p[v]));
  }

  void unite(int a, int b) {
    a = get(a), b = get(b);
    if (a != b) {
      if (s[a] > s[b]) swap(a, b);
      p[b] = a;
      s[a] += s[b];
    }
  }
};

const int B = 800;

void solve() {
  int n, m;
  cin >> n >> m;
  vector<array<int, 4>> edges(m);
  for (int i = 0; i < m; i++) {
    cin >> edges[i][0] >> edges[i][1] >> edges[i][2];
    --edges[i][0], --edges[i][1];
    edges[i][3] = i;
  }

  auto sorted = edges;
  sort(sorted.begin(), sorted.end(), [&] (const array<int, 4>& lhs, const array<int, 4>& rhs) {
    return lhs[2] > rhs[2];
  });

  int q;
  cin >> q;
  int cnt_blocks = (q + B - 1) / B;
  vector<vector<array<int, 3>>> qchange(cnt_blocks), qask(cnt_blocks);
  for (int i = 0; i < q; i++) {
    int t, a, b;
    cin >> t >> a >> b;
    if (t == 1) {
      qchange[i / B].push_back({a - 1, b, i});
    } else {
      qask[i / B].push_back({a - 1, b, i});
    }
  }

  vector<pair<int, int>> answer;
  for (int block = 0; block < cnt_blocks; block++) {
    reverse(qchange[block].begin(), qchange[block].end());
    sort(qask[block].begin(), qask[block].end(), [&] (const array<int, 3>& lhs, const array<int, 3>& rhs) {
      return lhs[1] > rhs[1];
    });

    vector<char> in(m), changed(m), used(n);
    for (auto &[edge, lol, kek] : qchange[block]) {
      in[edge] = 1;
    }

    DSU dsu(n);
    int ptr = -1;
    vector<vector<int>> g(n);
    for (auto &[s, w, i] : qask[block]) {
      while (ptr + 1 < m && sorted[ptr + 1][2] >= w) {
        ptr++;
        if (in[sorted[ptr][3]] == 1) {
          continue;
        }
        dsu.unite(sorted[ptr][0], sorted[ptr][1]);
      }
      for (auto &[edge, weight, id] : qchange[block]) {
        if (id <= i && changed[edge] == 0) {
          changed[edge] = 1;
          if (weight >= w) {
            g[dsu.get(edges[edge][0])].push_back(dsu.get(edges[edge][1]));
            g[dsu.get(edges[edge][1])].push_back(dsu.get(edges[edge][0]));
          }
        }
      }
      for (auto &[edge, weight, id] : qchange[block]) {
        if (id > i && changed[edge] == 0) {
          changed[edge] = 1;
          if (edges[edge][2] >= w) {
            g[dsu.get(edges[edge][0])].push_back(dsu.get(edges[edge][1]));
            g[dsu.get(edges[edge][1])].push_back(dsu.get(edges[edge][0]));
          }
        }
      }


      int res = 0;
      vector<int> vert;
      function<void(int)> dfs = [&] (int v) {
        used[v] = 1;
        res += dsu.s[v];
        vert.push_back(v);
        for (auto &u : g[v]) {
          if (!used[u]) {
            dfs(u);
          }
        }
      };
      dfs(dsu.get(s));
      for (auto &v : vert) {
        used[v] = 0;
      }

      for (auto &[edge, weight, id] : qchange[block]) {
        changed[edge] = 0;
        g[dsu.get(edges[edge][0])].clear();
        g[dsu.get(edges[edge][1])].clear();
      }

      answer.emplace_back(i, res);
    }

    vector<pair<int, int>> changes;
    for (auto &[edge, weight, id] : qchange[block]) {
      if (changed[edge] == 0) {
        changed[edge] = 1;
        edges[edge][2] = weight;
        changes.emplace_back(weight, edge);
      }
    }
    sort(changes.rbegin(), changes.rend());

    int chng = 0;
    vector<array<int, 4>> new_sorted;
    for (int i = 0; i < m; i++) {
      while (chng < (int) changes.size() && changes[chng].first >= sorted[i][2]) {
        new_sorted.push_back(edges[changes[chng].second]);
        chng++;
      }
      if (in[sorted[i][3]] == 0) {
        new_sorted.push_back(sorted[i]);
      }
    }

    while (chng < (int) changes.size()) {
      new_sorted.push_back(edges[changes[chng].second]);
      chng++;
    }

    swap(sorted, new_sorted);
  }

  sort(answer.begin(), answer.end());
  for (auto &[i, res] : answer) {
    cout << res << '\n';
  }
}

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  solve();
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...