Submission #683902

#TimeUsernameProblemLanguageResultExecution timeMemory
683902evenvalueBridges (APIO19_bridges)C++17
14 / 100
935 ms274136 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 = 500;

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) 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;
    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 speed;
    int start;

    bool operator<(const query &other) const {
      return speed > other.speed;
    }
  };

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

    bool operator<(const edge &other) const {
      return w > other.w;
    }
  };

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

  edge edges[m];
  for (int i = 0; i < m; i++) {
    edges[i].x = read::Int() - 1;
    edges[i].y = read::Int() - 1;
    edges[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.start = read::Int() - 1;
      cur.speed = read::Int();
      queries.push_back(cur);
    }
    if (blocks.back().size() == kBlockSize) blocks.emplace_back();
  }

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

  int ans[qq];
  vector<edge> connect[qq];

  for (int i = 0, j = 0; i < blocks.size(); i++) {
    const vector<update> &block = blocks[i];
    auto bridges = edges;

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

      const query qry = queries[j];
      for (const update &u : block) {
        if (u.index > qry.index) break;
        bridges[u.bridge].w = u.limit;
      }

      for (const update &u : block) {
        if (u.index == qq) continue;
        if (bridges[u.bridge].w < qry.speed) continue;
        connect[qry.index].push_back(bridges[u.bridge]);
      }
    }

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

    vector<edge> unchanged;
    for (int k = 0; k < m; k++) {
      const edge &bridge = bridges[k];
      if (bridge.change) continue;
      unchanged.push_back(bridge);
    }

    sort(unchanged.begin(), unchanged.end());
    sort(q.begin(), q.end());

    dsu d(n);

    int k = 0;
    for (const query qry : q) {
      while (k < unchanged.size() and unchanged[k].w >= qry.speed) {
        d.unite(unchanged[k].x, unchanged[k].y);
        k++;
      }

      int rollbacks = 0;
      for (const edge e : connect[qry.index]) {
        rollbacks += d.unite(e.x, e.y);
      }

      ans[qry.index] = d.size(qry.start);
      connect[qry.index].clear();

      while (rollbacks--) {
        d.rollback();
      }
    }

    for (const update &u : block) {
      if (u.index == qq) continue;
      edges[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:158: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]
  158 |   for (int i = 0, j = 0; i < blocks.size(); i++) {
      |                          ~~^~~~~~~~~~~~~~~
bridges.cpp:163:14: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<solution()::query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  163 |     for (; j < queries.size(); j++) {
      |            ~~^~~~~~~~~~~~~~~~
bridges.cpp:199:16: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<solution()::edge>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  199 |       while (k < unchanged.size() and unchanged[k].w >= qry.speed) {
      |              ~~^~~~~~~~~~~~~~~~~~
#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...