제출 #1130394

#제출 시각아이디문제언어결과실행 시간메모리
1130394fgdsaRoad Service 2 (JOI24_ho_t5)C++20
27 / 100
1594 ms388936 KiB
#include <bits/stdc++.h> using namespace std; int H, W; vector<int> koszt; vector<int> rodzic; vector<pair<int, int>> zakres; vector<pair<int, int>> tree; vector<pair<int, int>> lazy; vector<vector<int>> jump; int base; int LOG; int p, k; pair<int, int> val; void push(int v, int l, int r){ if(lazy[v].first > lazy[l].first) lazy[l] = lazy[v]; if(lazy[v].first > lazy[r].first) lazy[r] = lazy[v]; if(lazy[v].first > tree[l].first) tree[l] = lazy[v]; if(lazy[v].first > tree[r].first) tree[r] = lazy[v]; } void add(int v, int a, int b){ if(a > k || b < p || a > b) return; if(p <= a && b <= k){ if(val.first > tree[v].first) tree[v] = val; if(val.first > lazy[v].first) lazy[v] = val; return; } int l = 2*v, r = 2*v+1, mid = (a+b)/2; push(v, l, r); add(l, a, mid); add(r, mid+1, b); auto cl = tree[l]; auto cr = tree[r]; if(cl.first > cr.first) tree[v] = cl; else tree[v] = cr; } pair<int, int> query(int v, int a, int b){ if(a > k || b < p || a > b) return {0, 0}; if(p <= a && b <= k) return tree[v]; int l = 2*v, r = 2*v+1, mid = (a+b)/2; push(v, l, r); auto cl = query(l, a, mid); auto cr = query(r, mid+1, b); if(cl.first > cr.first) return cl; return cr; } int find(int x){ if(rodzic[x] != x) rodzic[x] = find(rodzic[x]); return rodzic[x]; } void wypisz(){ for(int i = 1; i <= H; ++i){ for(int j = 1; j <= W; ++j){ cerr << i << " " << j << ": " << i*W + j << "\n"; } } cerr << "\n\n"; for(int i = 1; i < (H+3)*(W+3); ++i){ cerr << i << ": " << rodzic[i] << "\n"; } cerr << "\n\n"; // for(int i = 1; i < (H+3)*(W+3); ++i){ // cerr << i << ": " << zakres[i].first << " " << zakres[i].second << "\n"; // } // cerr << "\n\n"; } void zrobCosZPrzedzialami(){ set<int> spojne; for(int i = 1; i <= H; ++i){ for(int j = 1; j <= W; ++j){ spojne.insert(find(i*W + j)); } } for(auto i : spojne){ p = zakres[i].first; k = zakres[i].second; val = {k, i}; // cerr << i << ": " << p << " " << k << '\n'; add(1, 1, base); } // cerr << "\n"; for(auto i : spojne){ p = zakres[i].first; k = zakres[i].second; auto q = query(1, 1, base); // cerr << i << ": " << q.first << " " << q.second << '\n'; jump[i][0] = q.second; } // cerr << "\n"; // for(auto i : spojne){ // cerr << i << ": " << jump[i][0] << '\n'; // } } int main(){ int q; cin >> H >> W >> q; LOG = log2(H)+2; base = 1<<(int)(log2(H)+1); rodzic.assign((H+3)*(W+3), 0); zakres.assign((H+3)*(W+3), {0, 0}); jump.assign((H+3)*(W+3), vector<int> (LOG)); tree.assign(2*base, {0, 0}); lazy.assign(2*base, {0, 0}); koszt.assign(H+3, 0); for(int i = 1; i <= H; ++i){ for(int j = 1; j <= W; ++j){ rodzic[i*W+j] = i*W+j; zakres[i*W+j] = {i, i}; } } for(int i = 1; i <= H; ++i){ for(int j = 1; j < W; ++j){ char c; cin >> c; if(c == '1'){ int p1 = find(i*W + j); int p2 = find(i*W + j+1); rodzic[p1] = p2; } } } for(int i = 1; i < H; ++i){ for(int j = 1; j <= W; ++j){ char c; cin >> c; if(c == '1'){ int p1 = find(i*W + j); int p2 = find((i+1)*W + j); rodzic[p1] = p2; zakres[p2].first = min(zakres[p2].first, zakres[p1].first); zakres[p2].second = max(zakres[p2].second, zakres[p1].second); } } } for(int i = 1; i <= H; ++i){ cin >> koszt[i]; } zrobCosZPrzedzialami(); for(int i = 1; i < LOG; ++i){ for(int j = 0; j <= H*W+W; ++j){ jump[j][i] = jump[jump[j][i-1]][i-1]; } } for(int i = 0; i < q; ++i){ int t; cin >> t; vector<int> punkty; for(int j = 0; j < t; ++j){ int x, y; cin >> x >> y; punkty.push_back(find(x*W + y)); } sort(punkty.begin(), punkty.end(), [&](const int & a, const int & b){ if(zakres[a].first == zakres[b].first) return zakres[a].second < zakres[b].second; return zakres[a].first < zakres[b].first; }); int start = punkty[0]; // cerr << start << " " << punkty.back() << "\n"; if(start == punkty.back()){ cout << 0 << "\n"; continue; } int res = 0; for(int j = LOG-1; j >= 0; --j){ // cerr << j << ": " << jump[start][j] << " " << zakres[jump[start][j]].second << '\n'; if(zakres[jump[start][j]].second < zakres[punkty.back()].first){ start = jump[start][j], res += (1<<j); } } // cerr << start << ": " << zakres[start].first << " " << zakres[start].second << "\n"; // cerr << punkty.back() << ": " << zakres[punkty.back()].first << " " << zakres[punkty.back()].second << '\n'; if(zakres[start].second < zakres[punkty.back()].first){ start = jump[start][0]; ++res; } // cerr << start << "\n"; if(start != punkty.back()) ++res; if(zakres[start].second < zakres[punkty.back()].first){ cout << -1 << "\n"; } else{ cout << res << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...