제출 #1286848

#제출 시각아이디문제언어결과실행 시간메모리
1286848SoMotThanhXuan다리 (APIO19_bridges)C++20
73 / 100
3038 ms5816 KiB
#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 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...