제출 #854900

#제출 시각아이디문제언어결과실행 시간메모리
854900JustInCase다리 (APIO19_bridges)C++17
0 / 100
3077 ms4980 KiB
#include <algorithm>
#include <cassert>
#include <iostream>
#include <stack>
#include <vector>

using namespace std;

const int BLOCK_SIZE = 317;

struct edge {
  int u, v, w;

  static bool compDecrW(const edge &e1, const edge &e2) { return e1.w >= e2.w; }
};

struct update {
  int e, w;
};

struct query {
  int id;
  int v, w;

  static bool compDecrW(const query &q1, const query &q2) {
    return q1.w >= q2.w;
  }
};

struct rollback_dsu {
  struct change {
    int oldRoot, newRoot;
  };

  vector<int> parent;
  vector<int> compSize;
  stack<change> changes;

  rollback_dsu(int cntNodes) {
    parent.resize(cntNodes);
    compSize.resize(cntNodes, 1);

    for (int i = 0; i < cntNodes; i++) {
      parent[i] = i;
    }
  }

  int findRoot(int x) {
    while (parent[x] != x)
      x = parent[x];
    return x;
  }

  void unite(int x, int y) {
    int rootX = findRoot(x);
    int rootY = findRoot(y);

    if (rootX == rootY)
      return;

    if (compSize[rootX] <= compSize[rootY]) {
      parent[rootX] = rootY;
      compSize[rootY] += compSize[rootX];
      changes.push(change{rootX, rootY});
    } else {
      parent[rootY] = rootX;
      compSize[rootX] += compSize[rootY];
      changes.push(change{rootY, rootX});
    }
  }

  void markAsStable() {
    while (!changes.empty())
      changes.pop();
  }

  void rollbackToStable() {
    while (!changes.empty()) {
      auto [oldRoot, newRoot] = changes.top();
      changes.pop();

      parent[oldRoot] = oldRoot;
      compSize[newRoot] -= compSize[oldRoot];
    }
  }
};

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

  int n, m;
  cin >> n >> m;

  vector<edge> edges(m);
  for (int i = 0; i < m; i++) {
    int u, v, w;
    cin >> u >> v >> w;

    u--;
    v--;

    edges[i] = edge{u, v, w};
  }

  int q;
  cin >> q;

  for (int i = 0; i < q; i += BLOCK_SIZE) {
    vector<int> t(BLOCK_SIZE);
    vector<bool> changed(m, false);
    vector<update> updates;
    vector<query> queries;
    for (int j = 0; j < min(BLOCK_SIZE, q - i); j++) {
      cin >> t[j];

      if (t[j] == 1) {
        int e, w;
        cin >> e >> w;

        e--;

        updates.push_back(update{e, w});
        changed[e] = true;
      } else {
        int v, w;
        cin >> v >> w;

        v--;

        queries.push_back(query{(int)queries.size(), v, w});
      }
    }

    vector<vector<edge>> additionalEdges(queries.size());
    int queryInd = 0, updateInd = 0;
    for (int j = 0; j < min(BLOCK_SIZE, q - i); j++) {
      if (t[j] == 1) {
        edges[updates[updateInd].e].w = updates[updateInd].w;
        updateInd++;
      } else {
        assert(queryInd < queries.size());
        for (auto u : updates) {
          if (edges[u.e].w >= queries[queryInd].w)
            additionalEdges[queryInd].push_back(edges[u.e]);
        }
        queryInd++;
      }
    }

    vector<edge> unchanged;
    for (int j = 0; j < m; j++) {
      if (!changed[j])
        unchanged.push_back(edges[j]);
    }

    sort(unchanged.begin(), unchanged.end(), edge::compDecrW);
    sort(queries.begin(), queries.end(), query::compDecrW);

    auto dsu = rollback_dsu(n);

    int edgePtr = 0;
    vector<int> ans(queries.size());
    for (int j = 0; j < queries.size(); j++) {
      while (edgePtr < unchanged.size() &&
             unchanged[edgePtr].w >= queries[j].w) {
        dsu.unite(unchanged[edgePtr].u, unchanged[edgePtr].v);
        edgePtr++;
      }

      dsu.markAsStable();

      while (!(queries[j].id >= 0 && queries[j].id < additionalEdges.size()))
        ;
      for (auto e : additionalEdges[queries[j].id]) {
        dsu.unite(e.u, e.v);
      }

      assert(queries[j].id >= 0 && queries[j].id < ans.size());
      ans[queries[j].id] = dsu.compSize[dsu.findRoot(queries[j].v)];

      dsu.rollbackToStable();
    }

    for (auto x : ans) {
      cout << x << endl;
    }
  }
}

컴파일 시 표준 에러 (stderr) 메시지

In file included from /usr/include/c++/10/cassert:44,
                 from bridges.cpp:2:
bridges.cpp: In function 'int main()':
bridges.cpp:142:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  142 |         assert(queryInd < queries.size());
      |                ~~~~~~~~~^~~~~~~~~~~~~~~~
bridges.cpp:164:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  164 |     for (int j = 0; j < queries.size(); j++) {
      |                     ~~^~~~~~~~~~~~~~~~
bridges.cpp:165:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<edge>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  165 |       while (edgePtr < unchanged.size() &&
      |              ~~~~~~~~^~~~~~~~~~~~~~~~~~
bridges.cpp:173:52: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<edge> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  173 |       while (!(queries[j].id >= 0 && queries[j].id < additionalEdges.size()))
In file included from /usr/include/c++/10/cassert:44,
                 from bridges.cpp:2:
bridges.cpp:179:50: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  179 |       assert(queries[j].id >= 0 && queries[j].id < ans.size());
#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...