Submission #1337168

#TimeUsernameProblemLanguageResultExecution timeMemory
1337168baodatBridges (APIO19_bridges)C++20
100 / 100
1240 ms8888 KiB
#include <bits/stdc++.h>
using namespace std;

#define ll long long 
#define FOR(i, l, r) for(int i = l; i <= r; i++)
#define FORD(i, l, r) for(int i = l; i >= r; i--)
#define db double
#define ldb long double
#define all_1(x) (x).begin() + 1, (x).end()
#define all(x) (x).begin(), (x).end()
#define ins insert
#define pb push_back

template<typename T>void debug_var(const T& var, const string& name){
    cerr << name << ": " << var << "\n";
}
template<typename T>void debug_1d(const T& vt, const string& name){
    if(vt.empty()){
        cerr << name << " is empty!\n";
        return;
    }
    FOR(i, 0, (int)vt.size() - 1){
        cerr << name << "[" << i << "]: " << vt[i] << "\n";
    }
}

struct Edge{
    int u, v, id;
    ll w; 
};

struct Data{
    int type, which;
    ll w;
    int id;
};

struct DSU_rollback{
    int _n;
    vector<int> _par, _rnk, _sz;
    struct History{
        int u, v, rnk_u, sz_u;
    };
    stack<History> history;
    DSU_rollback(int n = 0){
        init(n);
    }
    void init(int n){
        while(!history.empty()) history.pop();
        _n = n;
        _par.assign(n + 1, 0);
        _rnk.assign(n + 1, 0);
        _sz.assign(n + 1, 1); 
        iota(all(_par), 0);
    }
    int find_u(int u){
        return _par[u] == u ? u : find_u(_par[u]);
    }
    void unite(int u, int v){  
        u = find_u(u);
        v = find_u(v);
        if(u == v) return;
        
        if(_rnk[u] < _rnk[v]) swap(u, v);
        history.push({u, v, _rnk[u], _sz[u]});
        
        if(_rnk[u] == _rnk[v]) ++_rnk[u];
        _sz[u] += _sz[v];
        _par[v] = u;
    }
    void rollback(int target_size){
        while((int)history.size() > target_size){
            History cur = history.top();
            history.pop();
            _par[cur.v] = cur.v;
            _sz[cur.u] = cur.sz_u;
            _rnk[cur.u] = cur.rnk_u;
        }
    }
};

int n, m, q;

void solve(){
    if (!(cin >> n >> m)) return;
    vector<Edge> edges(m + 1);
    FOR(i, 1, m){
        cin >> edges[i].u >> edges[i].v >> edges[i].w;
        edges[i].id = i;
    }
    
    cin >> q;
    vector<Data> queries(q + 1);
    FOR(i, 1, q){
        cin >> queries[i].type >> queries[i].which >> queries[i].w;
        queries[i].id = i;
    }

    vector<int> ans(q + 1, 0);
    int BLOCK = 1000; 
    
    vector<int> sorted_edges;
    FOR(i, 1, m) sorted_edges.pb(i);
    
    sort(all(sorted_edges), [&](int a, int b){
        return edges[a].w > edges[b].w;
    });

    vector<ll> changed_weight(m + 1, -1);

    for(int L = 1; L <= q; L += BLOCK){
        int R = min(q, L + BLOCK - 1);
        
        vector<int> changed_edges, unchanged_edges, need_ans;
        vector<bool> is_changed(m + 1, false); 
        
        FOR(i, L, R){
            if(queries[i].type == 2) need_ans.pb(i);
            else is_changed[queries[i].which] = true;
        }
        
        for(int e : sorted_edges){
            if(is_changed[e]) changed_edges.pb(e);
            else unchanged_edges.pb(e);
        }
        
        sort(all(need_ans), [&](int a, int b){
            return queries[a].w > queries[b].w;
        });
        
        DSU_rollback dsu(n);
        int edge_ptr = 0;
        
        for(int q_idx : need_ans){
            while(edge_ptr < (int)unchanged_edges.size() && edges[unchanged_edges[edge_ptr]].w >= queries[q_idx].w){
                dsu.unite(edges[unchanged_edges[edge_ptr]].u, edges[unchanged_edges[edge_ptr]].v);
                edge_ptr++;
            }
            
            int checkpoint = dsu.history.size();
            
            for(int k = q_idx; k >= L; k--){
                if(queries[k].type == 1 && changed_weight[queries[k].which] == -1){
                    changed_weight[queries[k].which] = queries[k].w;
                }
            }
            
            for(int e_idx : changed_edges){
                ll weight_now = (changed_weight[e_idx] != -1) ? changed_weight[e_idx] : edges[e_idx].w;
                if(weight_now >= queries[q_idx].w){
                    dsu.unite(edges[e_idx].u, edges[e_idx].v);
                }
            }
            
            ans[q_idx] = dsu._sz[dsu.find_u(queries[q_idx].which)];
            dsu.rollback(checkpoint);
            
            for(int k = q_idx; k >= L; k--){
                if(queries[k].type == 1){
                    changed_weight[queries[k].which] = -1;
                }
            }
        }
        
        FOR(i, L, R){
            if(queries[i].type == 1){
                edges[queries[i].which].w = queries[i].w;
            }
        }
        
        sort(all(changed_edges), [&](int a, int b){
            return edges[a].w > edges[b].w;
        });
        
        sorted_edges.clear();
        merge(all(unchanged_edges), all(changed_edges), back_inserter(sorted_edges), [&](int a, int b){
            return edges[a].w > edges[b].w;
        });
    }
    
    FOR(i, 1, q) if(queries[i].type == 2) cout << ans[i] << "\n";
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    //cin >> t;
    while(t--){
        solve();
    }
    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...