Submission #975727

#TimeUsernameProblemLanguageResultExecution timeMemory
975727oviyan_gandhiBridges (APIO19_bridges)C++17
100 / 100
2296 ms25628 KiB
#pragma GCC optimize("Ofast,unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;

#define N 50001
#define M 100001
int lnk[N], sz[N];

inline void build(int n){
    fill(sz, sz+n+1, 1);
    iota(lnk, lnk+n+1, 0);
}

inline int root(int x){
    int l = x;
    while (lnk[l] != l) l = lnk[l];
    return lnk[x] = l;
}

inline void unite(int x, int y){
    x = root(x), y = root(y);
    if (x == y) return;
    if (sz[x] < sz[y]) swap(x, y);
    sz[x] += sz[y];
    lnk[y] = x;
}

struct Edge {
    int a, b, w, i;
    bool operator < (const Edge &o) const { return make_pair(w, i) > make_pair(o.w, o.i); }
} edges[M], queries[M], sorted_qu[M];
vector<int> adj[N];
bool vis[N];
int ans[M];

int32_t main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n, m; cin >> n >> m;
    for (int i = 1; i <= m; i++){
        cin >> edges[i].a >> edges[i].b >> edges[i].w;
        edges[i].i = i;
    }
    int q; cin >> q;
    for (int i = 1; i <= q; i++){
        cin >> queries[i].a >> queries[i].b >> queries[i].w;
        queries[i].i = i;
        sorted_qu[i] = queries[i];
    }

    set<Edge> sorted;
    for (int i = 1; i <= m; i++)
        sorted.insert(edges[i]);
    int bsz = ceil(sqrt(q));
    for (int s = 1; s <= q; s += bsz){
        build(n);
        map<int, int> changed;
        for (int i = s; i < min(q+1, s+bsz); i++)
            if (queries[i].a == 1)
                changed[queries[i].b] = edges[queries[i].b].w;
        for (auto [i, w] : changed)
            sorted.erase(edges[i]);
        sort(sorted_qu+s, sorted_qu+min(s+bsz, q+1));

        auto it = sorted.begin();
        for (int qi = s; qi < min(s+bsz, q+1); qi++){
            if (sorted_qu[qi].a == 1) continue;
            auto [_, start, w, idx] = sorted_qu[qi];
            for (; it != sorted.end() && it->w >= w; it++)
                unite(it->a, it->b);
            map<int, int> curr(changed);
            for (int i = s; i < idx; i++)
                if (queries[i].a == 1)
                    curr[queries[i].b] = queries[i].w;
            vector<int> graph;
            for (auto [ei, ew] : curr){
                if (ew >= w && root(edges[ei].a) != root(edges[ei].b)){
                    adj[root(edges[ei].a)].push_back(root(edges[ei].b));
                    adj[root(edges[ei].b)].push_back(root(edges[ei].a));
                    graph.push_back(root(edges[ei].a));
                    graph.push_back(root(edges[ei].b));
                }
            }

            queue<int> q;
            q.push(root(start));
            vis[root(start)] = true;
            graph.push_back(root(start));
            while (!q.empty()){
                int u = q.front();
                q.pop();
                ans[idx] += sz[u];
                for (int v : adj[u]){
                    if (!vis[v]){
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }

            for (int i : graph){
                vis[i] = false;
                adj[i].clear();
            }
        }

        for (int i = s; i < min(q+1, s+bsz); i++)
            if (queries[i].a == 1)
                changed[queries[i].b] = queries[i].w;
        for (auto [i, w] : changed){
            edges[i].w = w;
            sorted.insert(edges[i]);
        }
    }
    for (int i = 1; i <= q; i++)
        if (ans[i])
            cout << ans[i] << '\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...