제출 #848262

#제출 시각아이디문제언어결과실행 시간메모리
848262popovicirobert다리 (APIO19_bridges)C++14
59 / 100
3010 ms8348 KiB
#include <bits/stdc++.h> #define lsb(x) (x & (-x)) using ull = unsigned long long; using ll = long long; using namespace std; #ifdef HOME #define LOCAL_CHECK(x) assert(x); #else #define LOCAL_CHECK(x) #endif // https://judge.yosupo.jp/submission/159946 template<bool _CompressPath = true> class DSU { public: DSU(int n) : n(n) { LOCAL_CHECK(n > 0); link.resize(n, -1); size.resize(n, 1); } int getRoot(int x) noexcept { LOCAL_CHECK(0 <= x && x < n); if (_CompressPath) { return link[x] == -1 ? x : link[x] = getRoot(link[x]); } else { return link[x] == -1 ? x : getRoot(link[x]); } } bool join(int x, int y) noexcept(_CompressPath) { LOCAL_CHECK(0 <= x && x < n); LOCAL_CHECK(0 <= y && y < n); x = getRoot(x), y = getRoot(y); if (size[x] > size[y]) { std::swap(x, y); } bool joined = (x != y); if (joined) { link[x] = y; size[y] += size[x]; if (!_CompressPath) { joinedLinks.push(x); } } else { if (!_CompressPath) { joinedLinks.push(-1); } } return joined; } inline int getSize(int x) noexcept { return size[getRoot(x)]; } void undo() { static_assert(!_CompressPath); if (!joinedLinks.empty()) { auto lastJoin = joinedLinks.top(); joinedLinks.pop(); if (lastJoin == -1) return; size[link[lastJoin]] -= size[lastJoin]; link[lastJoin] = -1; } else { assert(false); } } private: std::vector<int> link; std::vector<int> size; int n; std::stack<int> joinedLinks; }; struct Edge { int x, y, w; }; struct Update { int edgeId; int w; int pos; }; struct Query { int node; int w; int pos; }; int main() { #ifdef HOME ifstream cin("input.in"); ofstream cout("output.out"); #endif ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int n, m; cin >> n >> m; vector<Edge> edges(m); for (auto& e : edges) { cin >> e.x >> e.y >> e.w; } vector<int> markedEdges(m, -1); vector<int> markedUpdatedEdges(m, -1); vector<int> edgeOrder(m); iota(edgeOrder.begin(), edgeOrder.end(), 0); DSU<false> dsu(n + 1); const int LIM = sqrt(n); int q; cin >> q; vector<int> result(q, -1); for (int qq = 0; qq < q; qq += LIM) { vector<Query> queries; vector<Update> updates; vector<int> currentEdges; for (int i = 0; i < q - qq && i < LIM; i++) { int t; cin >> t; if (t == 1) { int edgeId, w; cin >> edgeId >> w; edgeId--; updates.push_back({edgeId, w, i + qq}); if (markedEdges[edgeId] != qq) { currentEdges.push_back(edgeId); } markedEdges[edgeId] = qq; } else { int node, w; cin >> node >> w; queries.push_back({node, w, i + qq}); } } sort(queries.begin(), queries.end(), [](const Query& a, const Query& b) { return a.w > b.w; }); sort(edgeOrder.begin(), edgeOrder.end(), [&](const int& a, const int& b) { return edges[a].w > edges[b].w; }); int pos = 0; for (auto& query : queries) { while (pos < m && edges[edgeOrder[pos]].w >= query.w) { int edgeId = edgeOrder[pos]; if (markedEdges[edgeId] != qq) { dsu.join(edges[edgeId].x, edges[edgeId].y); } pos++; } static int currentIteration = -1; currentIteration++; int i = 0; while (i < (int)updates.size() && updates[i].pos <= query.pos) { i++; } i--; int j = 0; while (i >= 0) { int edgeId = updates[i].edgeId; if (markedUpdatedEdges[edgeId] != currentIteration) { markedUpdatedEdges[edgeId] = currentIteration; if (query.w <= updates[i].w) { dsu.join(edges[edgeId].x, edges[edgeId].y); j++; } } i--; } for (auto edgeId : currentEdges) { if (markedUpdatedEdges[edgeId] != currentIteration && edges[edgeId].w >= query.w) { dsu.join(edges[edgeId].x, edges[edgeId].y); j++; } } result[query.pos] = dsu.getSize(query.node); while (j > 0) { dsu.undo(); j--; } } for (int i = pos - 1; i >= 0; i--) { if (markedEdges[edgeOrder[i]] != qq) { dsu.undo(); } } for (auto& update : updates) { edges[update.edgeId].w = update.w; } } for (auto itr : result) { if (itr != -1) { cout << itr << "\n"; } } 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...