Original question link
Idea: we think about accessibility. The accessibility of each grid comes from the grid on the left and the grid above. Let's take the first behavior as an example. Why can't all points on the right of the first mine in the first row be reached? Because this mine cuts off all the remaining schemes from the left, and there is no scheme above, the accessibility of all the remaining grids is 0.
Similarly, all the remaining grids can think like this. After a line encounters a mine, we need to see if there is a reachable grid on the remaining grid. If there is a reachable grid on it, this grid can also be reached. Because this grid can be reached, all grids on its right (until the next mine position of the line) have more accessibility from the left, Therefore, the grid of this position until the next mine becomes reachable. Even if the grids above those grids are unreachable, it does not affect them, because the upper grid gives them accessibility from the top, while the accessible grid on the left has given them accessibility from the left. As long as any grid on the top and left is reachable, then this grid is reachable. Therefore, when we meet a mine, what we need to find is whether there is a reachable grid from above at the position of the mine to the next mine. If so, then all the positions from this grid to the next mine-1 will be reachable.
As shown in the figure, as long as there is a reachable point from above between two mines, it is reachable until the position of the next mine.
What we need to query is whether there is an reachable point in the previous line at the position of i + 1 ~ x - 1. If it is reachable, pos ~ x - 1 is assigned to 1
How to enumerate the locations of two mines at the same time? We can define an l as the previous mine, the initial l=0, and the mine also represents the unreachable position, so it is also possible to define 0. Just enumerate the next mine at the same time.
I use line segment tree.
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <math.h> #include <map> #include <set> #include <queue> using namespace std; #define endl '\n' #define lson node << 1 #define rson node << 1 | 1 const int maxn = 1e5 + 5; const int inf = 1e9; struct node{ int val,laz; }t[2][maxn << 2]; int n,m,k; vector<int> g[maxn]; void pushup(int c,int node){ t[c][node].val = t[c][lson].val + t[c][rson].val; } void spread(int c,int node,int l,int r){ if (t[c][node].laz == -1) return; int mid = l + r >> 1; int &k = t[c][node].laz; t[c][lson].val = (mid - l + 1) * k; t[c][rson].val = (r - mid) * k; t[c][lson].laz = t[c][rson].laz = k; k = -1; } void build(int c,int l,int r,int node){ t[c][node].laz = -1; if (l == r){ t[c][node].val = 0; return; } int mid = l + r >> 1; build(c,l,mid,lson); build(c,mid + 1,r,rson); pushup(c,node); } void update(int c,int l,int r,int x,int y,int node,int k){ if (x <= l && r <= y){ t[c][node].val = (r - l + 1) * k; t[c][node].laz = k; return; } int mid = l + r >> 1; spread(c,node,l,r); if (x <= mid) update(c,l,mid,x,y,lson,k); if (y > mid) update(c,mid + 1,r,x,y,rson,k); pushup(c,node); } int query(int c,int l,int r,int x,int y,int node){ if (!t[c][node].val) return inf; if (l == r) return l; int mid = l + r >> 1; spread(c,node,l,r); if (x <= l && r <= y){ if (t[c][lson].val) return query(c,l,mid,x,y,lson); else return query(c,mid + 1,r,x,y,rson); } int ans = inf; if (x <= mid) ans = min(ans, query(c,l,mid,x,y,lson)); if (y > mid) ans = min(ans, query(c,mid + 1,r,x,y,rson)); return ans; } void solve(){ cin >> n >> m >> k; for (int i = 1; i <= n; ++i) { g[i].clear(); } long long ans = 0; for (int i = 1; i <= k; ++i) { int x,y; cin >> x >> y; g[x].push_back(y); } for (int i = 0; i <= 1; ++i) { build(i,1,m,1); } int now = 0; update(now,1,m,1,1,1,1); now ^= 1; for (int i = 1; i <= n; ++i) { sort(g[i].begin(),g[i].end()); int l = 0; for(auto x : g[i]){ if (l + 1 <= x - 1){ int pos = query(now ^ 1,1,m,l + 1,x - 1,1); if (pos != inf) update(now,1,m,pos,x - 1,1,1); } l = x; } if (l + 1 <= m){ int pos = query(now ^ 1,1,m,l + 1,m,1); if (pos != inf) update(now,1,m,pos,m,1,1); } ans += t[now][1].val; update(now ^ 1,1,m,1,m,1,0); now ^= 1; } cout << ans << endl; } int main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--) solve(); }