Submission #1159459

#TimeUsernameProblemLanguageResultExecution timeMemory
1159459Zero_OPFurniture (JOI20_furniture)C++20
0 / 100
104 ms251256 KiB
#include <bits/stdc++.h> using namespace std; //loops (warning : long long) #define FOR(i, l, r) for(int i = (l); i < (r); ++i) #define ROF(i, r, l) for(int i = (r - 1); i >= l; --i) //pairs, tuples #define mp make_pair #define mt make_tuple #define ff first #define ss second //vectors #define all(v) begin(v), end(v) #define rall(v) rbegin(v), rend(v) #define pb push_back #define eb emplace_back #define sum_of(v) accumulate(all(v), 0ll) #define sz(v) (int)v.size() #define compact(v) v.erase(unique(all(v)), end(v)) //binary search #define lwb lower_bound #define upb upper_bound //other stuffs #define dbg(x) "[" #x " = " << (x) << "]" #define file(task) if(fopen(task".inp", "r")){ freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); } template<typename T> bool minimize(T& a, const T& b){ if(a > b) return a = b, true; return false; } template<typename T> bool maximize(T& a, const T& b){ if(a < b) return a = b, true; return false; } using ll = long long; using ull = unsigned long long; using ld = long double; using db = double; using pi = pair<int, int>; using pl = pair<ll, ll>; using vi = vector<int>; using vb = vector<bool>; using vl = vector<ll>; using vpi = vector<pi>; using vpl = vector<pl>; mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); const int NUMNODES = (int)1e6 * 21; const int mod = 1e9 + 9; struct mint{ int v; mint() : v(0) {} mint(int v) : v(v) {} mint& operator += (const mint& o){ v += o.v; if(v >= mod) v -= mod; return *this; } mint& operator -= (const mint& o){ v -= o.v; if(v < 0) v += mod; return *this; } mint& operator *= (const mint& o){ v = 1LL * v * o.v % mod; return *this; } friend mint operator + (mint a, const mint& b){ return a += b ;} friend mint operator - (mint a, const mint& b){ return a -= b ;} friend mint operator * (mint a, const mint& b){ return a *= b ;} friend bool operator == (const mint& a, const mint& b){ return a.v == b.v; } friend bool operator != (const mint& a, const mint& b){ return a.v != b.v; } friend ostream& operator << (ostream& out, const mint& o){ return out << o.v; } }; int nnodes = 0; mint pw3[(int)1e6 + 1]; struct node{ int ln, rn; mint hsh; } st[NUMNODES]; int build(int l, int r){ if(l == r){ return 2; } int mid = l + r >> 1, o = ++nnodes; st[o].ln = build(l, mid); st[o].rn = build(mid+1, r); st[o].hsh = st[st[o].ln].hsh * pw3[mid - l + 1] + st[st[o].rn].hsh; return o; } int set_zero(int t, int l, int r, int pos){ if(l == r){ return 1; } else{ int mid = l + r >> 1, o = ++nnodes; st[o].ln = st[t].ln; st[o].rn = st[t].rn; if(pos <= mid) st[o].ln = set_zero(st[t].ln, l, mid, pos); else st[o].rn = set_zero(st[t].rn, mid + 1, r, pos); st[o].hsh = st[st[o].ln].hsh * pw3[mid - l + 1] + st[st[o].rn].hsh; return o; } } bool walk(int v1, int v2, int l, int r){ while(l < r){ int mid = l + r >> 1; if(st[st[v1].ln].hsh != st[st[v2].ln].hsh) r = mid, v1 = st[v1].ln, v2 = st[v2].ln; else l = mid + 1, v1 = st[v1].rn, v2 = st[v2].rn; } assert(st[v1].hsh != st[v2].hsh); return st[v1].hsh.v > st[v2].hsh.v; } void trace(int v, int l, int r, vb& result){ if(l == r){ result[l] = st[v].hsh.v - 1; } else{ int mid = l + r >> 1; trace(st[v].ln, l, mid, result); trace(st[v].rn, mid + 1, r, result); } } void debug(int id, int l, int r){ if(l == r) cout << st[id].hsh.v - 1; else{ int mid = l + r >> 1; debug(st[id].ln, l, mid); debug(st[id].rn, mid + 1, r); } } void testcase(int ntestcase){ nnodes += 3; st[1].hsh.v = 1; st[2].hsh.v = 2; int N, M; cin >> N >> M; vector<vi> a(N, vi(M)); FOR(i, 0, N){ FOR(j, 0, M){ cin >> a[i][j]; } } vector<int> obstacles(N * M, -1); int Q; cin >> Q; FOR(i, 0, Q){ int x, y; cin >> x >> y; --x, --y; int p = x * M + y; assert(obstacles[p] == -1); // cout << dbg(p) << dbg(i) << '\n'; obstacles[p] = i; } pw3[0] = 1; FOR(i, 1, Q){ pw3[i] = pw3[i-1] * mint(3); } vector<vi> dp(N, vi(M, -1)); dp[0][0] = build(0, Q-1); auto calc_dp = [&](int i, int j){ if(i == 0) dp[i][j] = dp[i][j-1]; else if(j == 0) dp[i][j] = dp[i-1][j]; else{ if(dp[i-1][j] == -1 && dp[i][j-1] == -1) dp[i][j] = -1; else if(dp[i-1][j] == -1) dp[i][j] = dp[i][j-1]; else if(dp[i][j-1] == -1) dp[i][j] = dp[i-1][j]; else { if(st[dp[i-1][j]].hsh == st[dp[i][j-1]].hsh) dp[i][j] = dp[i-1][j]; else dp[i][j] = walk(dp[i-1][j], dp[i][j-1], 0, Q-1) ? dp[i-1][j] : dp[i][j-1]; } } }; FOR(i, 0, N){ FOR(j, (i == 0), M) { if(a[i][j] == 1) continue; calc_dp(i, j); if(obstacles[i * M + j] != -1 && dp[i][j] != -1){ dp[i][j] = set_zero(dp[i][j], 0, Q-1, obstacles[i * M + j]); } } } // FOR(i, 0, N){ // FOR(j, 0, M){ // cout << "(" << i << ", " << j << ") : "; // if(dp[i][j] == -1) cout << -1 << '\n'; // else{ // debug(dp[i][j], 0, Q-1); // cout << '\n'; // } // } // } vb result(Q); trace(dp[N-1][M-1], 0, Q-1, result); FOR(i, 0, Q){ cout << result[i] << '\n'; } } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); #ifdef LOCAL freopen("task.inp", "r", stdin); freopen("task.out", "w", stdout); #endif // LOCAL int T = 1; // cin >> T; FOR(i, 0, T) testcase(i); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...