Submission #706794

#TimeUsernameProblemLanguageResultExecution timeMemory
706794sharaelongBridges (APIO19_bridges)C++17
73 / 100
3051 ms21264 KiB
#include <bits/stdc++.h>
#ifdef SHARAELONG
#include "../../cpp-header/debug.hpp"
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;

struct DisjointSet {
    int n;
    vector<int> parent, size;
    vector<pii> history;
    DisjointSet(int _n) : n(_n) {
        parent.resize(n);
        iota(parent.begin(), parent.end(), 0);
        size.resize(n, 1);
    }

    int find(int u) {
        for (; u != parent[u]; u = parent[u]);
        return u;
    }

    void merge(int u, int v) {
        // print(u, v);
        u = find(u); v = find(v);
        if (u == v) {
            history.push_back({ -1, -1 });
            return;
        }
        if (size[u] > size[v]) swap(u, v);
        history.push_back({ u, v });
        parent[u] = v;
        size[v] += size[u];
    }

    void undo() {
        auto[u, v] = history.back();
        history.pop_back();
        if (u == -1) return;
        parent[u] = u;
        size[v] -= size[u];
    }
};

void solve() {
    int n, m;
    cin >> n >> m;
    vector<pair<pii, vector<int>>> adj(m);
    for (int i=0; i<m; ++i) {
        int u, v, d;
        cin >> u >> v >> d;
        adj[i] = { { u, v }, { d } };
    }

    int q;
    cin >> q;
    vector<int> ans(q, -1);
    vector<tuple<int, int, int>> queries(q);
    for (auto&[t, a, b]: queries) cin >> t >> a >> b;

    vector<int> cc;
    for (int i=0; i<m; ++i) cc.push_back(adj[i].second.back());
    for (int i=0; i<q; ++i) cc.push_back(get<2>(queries[i])); // two query format is common for weight
    sort(cc.begin(), cc.end());
    cc.erase(unique(cc.begin(), cc.end()), cc.end());
    for (int i=0; i<m; ++i) adj[i].second.back() = lower_bound(cc.begin(), cc.end(), adj[i].second.back()) - cc.begin();
    for (int i=0; i<q; ++i) get<2>(queries[i]) = lower_bound(cc.begin(), cc.end(), get<2>(queries[i])) - cc.begin();
    
    DisjointSet dsu(n+1);
    vector<vector<int>> edges(cc.size());
    vector<int> updated(m, false);
    
    int block = 1300;
    for (int i=0; i<q/block+1; ++i) {
        for (int j=0; j<edges.size(); ++j) edges[j].clear();
        vector<pii> block_queries;
        for (int j=i*block; j<min((i+1)*block, q); ++j) {
            if (get<0>(queries[j]) == 1) {
                int e = get<1>(queries[j])-1;
                updated[e] = true;
            } else {
                block_queries.push_back({ -get<2>(queries[j]), j });
            }
        }
        sort(block_queries.begin(), block_queries.end());

        for (int j=0; j<m; ++j) {
            if (!updated[j]) edges[adj[j].second.back()].push_back(j);
        }

        int curr_val = (int)edges.size()-1;
        for (auto[w, j]: block_queries) {
            int s = get<1>(queries[j]);
            w = -w;
            while (curr_val >= w) {
                for (int e: edges[curr_val]) {
                    auto[u, v] = adj[e].first;
                    dsu.merge(u, v);
                }
                curr_val--;
            }
            for (int k=i*block; k<j; ++k) {
                auto[t, b, r] = queries[k];
                if (t == 1) adj[b-1].second.push_back(r);
            }
            for (int k=i*block; k<min((i+1)*block, q); ++k) {
                auto[t, b, r] = queries[k];
                // print(w, j, k, t, b, r);
                // print(adj[b-1].second.size());
                if (t == 1 && adj[b-1].second.back() >= w) {
                    auto[u, v] = adj[b-1].first;
                    dsu.merge(u, v);
                }
            }
            
            ans[j] = dsu.size[dsu.find(s)];

            // no needs for iterating k reversely
            for (int k=i*block; k<min((i+1)*block, q); ++k) {
                auto[t, b, r] = queries[k];
                if (t == 1 && adj[b-1].second.back() >= w) {
                    dsu.undo();
                }
            }
            for (int k=i*block; k<j; ++k) {
                auto[t, b, r] = queries[k];
                if (t == 1) adj[b-1].second.pop_back();
            }
        }
        
        for (int k=curr_val+1; k<edges.size(); ++k) {
            for (int _: edges[k]) dsu.undo();
        }

        for (int j=i*block; j<min((i+1)*block, q); ++j) {
            if (get<0>(queries[j]) == 1) {
                int e = get<1>(queries[j])-1;
                updated[e] = false;
            }
        }

        for (int j=i*block; j<min((i+1)*block, q); ++j) {
            auto[t, b, r] = queries[j];
            if (t == 1) adj[b-1].second.push_back(r);
        }
    }

    for (int i=0; i<q; ++i) {
        if (ans[i] != -1) cout << ans[i] << '\n';
    }
}

int main() {
    // freopen("../../test.in", "r", stdin);
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    solve();
}

Compilation message (stderr)

bridges.cpp: In function 'void solve()':
bridges.cpp:76:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   76 |         for (int j=0; j<edges.size(); ++j) edges[j].clear();
      |                       ~^~~~~~~~~~~~~
bridges.cpp:132:33: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  132 |         for (int k=curr_val+1; k<edges.size(); ++k) {
      |                                ~^~~~~~~~~~~~~
bridges.cpp:133:22: warning: unused variable '_' [-Wunused-variable]
  133 |             for (int _: edges[k]) dsu.undo();
      |                      ^
#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...