제출 #854932

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

using namespace std;

const int BLOCK_SIZE = 1000;

struct edge {
  int u, v, w;

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

struct update {
  int e, w;
};

struct query {
  int id;
  int v, w;

  static bool compDecrW(query &q1, 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;

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

    fill(changed.begin(), changed.end(), false);

    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();

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