Submission #683736

#TimeUsernameProblemLanguageResultExecution timeMemory
683736evenvalueBridges (APIO19_bridges)C++17
14 / 100
1065 ms11744 KiB
#include <bits/stdc++.h>
using namespace std;

#ifdef evenvalue
  #include "debug.h"
  #define debug(...) print(#__VA_ARGS__, __VA_ARGS__)
#else
  #define debug(...)
#endif

using int64 = long long;
using ld = long double;

template<typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
template<typename T>
using max_heap = priority_queue<T, vector<T>, less<T>>;

namespace read {
int Int() {
  int x;
  cin >> x;
  return x;
}
}//namespace read

constexpr int kInf = 1e9 + 10;
constexpr int64 kInf64 = 1e15 + 10;
constexpr int kMod = 1e9 + 7;
constexpr int kBlockSize = 400;

class dsu {
  int n;
  std::vector<int> e;
  vector<pair<int, int>> history;

  int pfind(const int x) {
    return (e[x] < 0 ? x : pfind(e[x]));
  }

public:
  dsu() : n(0), comp(0) {}
  explicit dsu(const int n) : n(n), comp(n), e(n, -1) {}

  int comp;

  int find(const int x) {
    assert(0 <= x and x < n);
    return pfind(x);
  }

  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) {
      history.emplace_back(kInf, kInf);
      return false;
    }
    if (e[x] > e[y]) swap(x, y);
    history.emplace_back(y, e[y]);
    e[x] += e[y];
    e[y] = x;
    comp--;
    return true;
  }

  bool rollback() {
    if (history.empty()) return false;
    if (history.back() != make_pair(kInf, kInf)) {
      const int y = history.back().first;
      const int x = find(y);
      e[x] -= history.back().second;
      e[y] = history.back().second;
    }
    history.pop_back();
    return true;
  }

  bool same(const int x, const int y) {
    return (find(x) == find(y));
  }

  int size(const int x) {
    return -e[find(x)];
  }

  std::vector<std::vector<int>> components() {
    std::vector<std::vector<int>> res(n);
    for (int x = 0; x < n; x++) {
      res[pfind(x)].push_back(x);
    }
    res.erase(
        std::remove_if(res.begin(), res.end(), [&](const std::vector<int> &v) { return v.empty(); }),
        res.end()
    );
    return res;
  }
};

inline void solution() {
  struct update {
    int index;
    int bridge;
    int limit;
  };

  struct query {
    int index;
    int weight;
    int source;
  };

  struct bridge {
    int x = -1;
    int y = -1;
    int w = -1;
    bool change = false;
  };

  const int n = read::Int();
  const int m = read::Int();

  vector<bridge> bridges(m);
  for (int i = 0; i < m; i++) {
    bridges[i].x = read::Int() - 1;
    bridges[i].y = read::Int() - 1;
    bridges[i].w = read::Int();
  }

  vector<vector<update>> blocks = {{}};
  vector<query> queries;

  const int qq = read::Int();
  for (int i = 0; i < qq; i++) {
    const int t = read::Int();
    if (t == 1) {
      update cur{};
      cur.index = i;
      cur.bridge = read::Int() - 1;
      cur.limit = read::Int();
      blocks.back().push_back(cur);
    } else {
      query cur{};
      cur.index = i;
      cur.source = read::Int() - 1;
      cur.weight = read::Int();
      queries.push_back(cur);
    }
    if (blocks.back().size() == kBlockSize) blocks.emplace_back();
  }

  blocks.back().push_back({qq, -1, kInf});

  vector<int> ans(qq);
  for (int i = 0, j = 0; i < blocks.size(); i++) {
    const vector<update> &block = blocks[i];
    const int last_index = block.back().index;

    vector<query> q;
    for (; j < queries.size(); j++) {
      if (queries[j].index > last_index) break;
      q.push_back(queries[j]);
    }

    sort(q.begin(), q.end(), [&](const query &q1, const query &q2) {
      return q1.weight > q2.weight;
    });

    vector<bridge> edges = bridges;
    for (const update &u : block) {
      if (u.index == qq) continue;
      edges[u.bridge].change = true;
    }

    sort(edges.begin(), edges.end(), [&](const bridge &e1, const bridge &e2) {
      return e1.w > e2.w;
    });

    dsu d(n);
    for (int qry = 0, edge = 0; qry < q.size(); qry++) {
//      const auto [index, weight, source] = q[qry];
      const int index = q[qry].index;
      const int weight = q[qry].weight;
      const int source = q[qry].source;

      while (edge < edges.size() and edges[edge].w >= weight) {
        if (not edges[edge].change) {
          d.unite(edges[edge].x, edges[edge].y);
        }
        edge++;
      }

      int rollbacks = 0;
      for (const update &u : block) {
        if (u.index == qq) continue;
        const auto [x, y, w, _] = bridges[u.bridge];
        if (u.index < index and weight <= u.limit) {
          rollbacks++;
          d.unite(x, y);
        }
        if (u.index > index and weight <= w) {
          rollbacks++;
          d.unite(x, y);
        }
      }

      ans[index] = d.size(source);
      while (rollbacks--) {
        assert(d.rollback());
      }
    }

    for (const update &u : block) {
      if (u.index == qq) continue;
      bridges[u.bridge].w = u.limit;
    }
  }

  for (const query q : queries) {
    cout << ans[q.index] << '\n';
  }
}


int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);

  cout << fixed << setprecision(10);

  int testcases = 1;
  //cin >> testcases;
  while (testcases--) {
    solution();
  }
}

Compilation message (stderr)

bridges.cpp: In constructor 'dsu::dsu(int)':
bridges.cpp:45:7: warning: 'dsu::comp' will be initialized after [-Wreorder]
   45 |   int comp;
      |       ^~~~
bridges.cpp:34:20: warning:   'std::vector<int> dsu::e' [-Wreorder]
   34 |   std::vector<int> e;
      |                    ^
bridges.cpp:43:12: warning:   when initialized here [-Wreorder]
   43 |   explicit dsu(const int n) : n(n), comp(n), e(n, -1) {}
      |            ^~~
bridges.cpp: In function 'void solution()':
bridges.cpp:154:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<solution()::update> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  154 |   for (int i = 0, j = 0; i < blocks.size(); i++) {
      |                          ~~^~~~~~~~~~~~~~~
bridges.cpp:159:14: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<solution()::query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  159 |     for (; j < queries.size(); j++) {
      |            ~~^~~~~~~~~~~~~~~~
bridges.cpp:179:37: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<solution()::query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  179 |     for (int qry = 0, edge = 0; qry < q.size(); qry++) {
      |                                 ~~~~^~~~~~~~~~
bridges.cpp:185:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<solution()::bridge>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  185 |       while (edge < edges.size() and edges[edge].w >= weight) {
      |              ~~~~~^~~~~~~~~~~~~~
#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...