#ifdef ONLINE_JUDGE
#endif // ONLINE_JUDGE
#include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
#define FOR(i, a, b) for(int i = (a), _b = (b); i <= _b; ++i)
#define FORD(i, a, b) for(int i = (a), _b = (b); i >= _b; --i)
#define REP(i, n) for(int i = 0, _n = (n); i < _n; ++i)
#define mp make_pair
#define all(v) v.begin(), v.end()
#define uni(v) v.erase(unique(all(v)), v.end())
const int maxN = 100000 + 5;
int n, m, q;
pair<int,int> edge[maxN];
int w[maxN];
int type[maxN], cen[maxN], reqW[maxN];
int ans[maxN];
// simple rollback DSU (no path compression), union by size
struct RollbackDSU {
    int n;
    vector<int> parent, sz;
    vector<pair<int,int>> ops; // (v, old_sz_of_root) store v's parent before union and size of new root before merge
    RollbackDSU(int n = 0){ init(n); }
    void init(int _n){
        n = _n;
        parent.assign(n+1, 0);
        sz.assign(n+1, 0);
        for(int i=1;i<=n;i++){ parent[i]=i; sz[i]=1; }
        ops.clear();
    }
    int find(int v){
        while(parent[v] != v) v = parent[v];
        return v;
    }
    bool unite(int a, int b){
        a = find(a); b = find(b);
        if(a == b) return false;
        if(sz[a] < sz[b]) swap(a,b);
        // record b's parent and size of a before merge
        ops.emplace_back(b, sz[a]);
        parent[b] = a;
        sz[a] += sz[b];
        return true;
    }
    void rollbackOne(){
        if(ops.empty()) return;
        auto pr = ops.back(); ops.pop_back();
        int b = pr.first;
        int old_sz_a = pr.second;
        int a = parent[b]; // current parent
        // revert
        sz[a] = old_sz_a;
        parent[b] = b;
    }
    void rollbackToSize(size_t s){
        while(ops.size() > s) rollbackOne();
    }
    int compSize(int v){
        int r = find(v);
        return sz[r];
    }
};
struct Snapshot {
    int idx; // original query index
    int s;   // start node
    int w;   // threshold
    vector<int> changed_applicable; // ids of changed edges that meet threshold at query time
};
void process(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    if(!(cin >> n >> m)) return;
    FOR(i,1,m){
        int u,v,d; cin >> u >> v >> d;
        edge[i] = {u,v};
        w[i] = d;
    }
    cin >> q;
    FOR(i,1,q){
        cin >> type[i] >> cen[i] >> reqW[i];
    }
    RollbackDSU dsu(n);
    int BLOCK = max(1, (int)sqrt(q) ); // good default
    for(int L = 1; L <= q; L += BLOCK){
        int R = min(q, L + BLOCK - 1);
        // 1) find changed edge ids in this block
        vector<char> isChanged(m+1, 0);
        for(int i = L; i <= R; ++i){
            if(type[i] == 1){
                isChanged[cen[i]] = 1;
            }
        }
        vector<int> changedIds;
        changedIds.reserve(BLOCK);
        for(int eid = 1; eid <= m; ++eid) if(isChanged[eid]) changedIds.push_back(eid);
        // 2) unchanged edges list (weight, id) using current global w[]
        vector<pair<int,int>> unchanged;
        unchanged.reserve(m);
        for(int eid = 1; eid <= m; ++eid){
            if(!isChanged[eid]) unchanged.emplace_back(w[eid], eid);
        }
        sort(unchanged.begin(), unchanged.end(), [](const pair<int,int>& a, const pair<int,int>& b){
            return a.first > b.first; // descending by weight
        });
        // 3) simulate block to build snapshots for queries: need tmpW that applies updates inside block sequentially
        vector<int> tmpW(m+1);
        FOR(eid,1,m) tmpW[eid] = w[eid];
        vector<Snapshot> snaps;
        snaps.reserve(R-L+1);
        for(int i = L; i <= R; ++i){
            if(type[i] == 1){
                // apply update to tmpW for subsequent queries in this block
                int bid = cen[i], neww = reqW[i];
                tmpW[bid] = neww;
            } else {
                Snapshot s;
                s.idx = i;
                s.s = cen[i];
                s.w = reqW[i];
                // collect changed edges with tmpW >= s.w
                for(int id: changedIds){
                    if(tmpW[id] >= s.w) s.changed_applicable.push_back(id);
                }
                snaps.push_back(move(s));
            }
        }
        // 4) sort snapshots by w desc and process: add unchanged edges progressively, union changed_applicable per snapshot (with rollback)
        int szSnaps = (int)snaps.size();
        vector<int> order(szSnaps);
        iota(order.begin(), order.end(), 0);
        sort(order.begin(), order.end(), [&](int a, int b){
            return snaps[a].w > snaps[b].w;
        });
        // init DSU
        dsu.init(n);
        size_t ptr = 0; // pointer in unchanged
        for(int ordIdx = 0; ordIdx < szSnaps; ++ordIdx){
            Snapshot &S = snaps[order[ordIdx]];
            // bring unchanged edges with weight >= S.w
            while(ptr < unchanged.size() && unchanged[ptr].first >= S.w){
                int eid = unchanged[ptr].second;
                dsu.unite(edge[eid].first, edge[eid].second);
                ++ptr;
            }
            size_t saveSize = dsu.ops.size();
            // add changed_applicable temporarily
            for(int eid : S.changed_applicable){
                dsu.unite(edge[eid].first, edge[eid].second);
            }
            ans[S.idx] = dsu.compSize(S.s);
            dsu.rollbackToSize(saveSize);
        }
        // 5) apply all updates in block to global w[]
        for(int i = L; i <= R; ++i){
            if(type[i] == 1){
                int bid = cen[i], neww = reqW[i];
                w[bid] = neww;
            }
        }
    }
    FOR(i,1,q){
        if(type[i] == 2) cout << ans[i] << '\n';
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    process();
    return 0;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |