原题链接
题意:
n*m的棋盘,k个地雷,从(1,1)开始走,只能走右下两个方向,显然地雷不能走,问能到达的格子数
思路:
两棵线段树维护一下上一次层能到的区间,然后根据这一层的地雷位置推出理论上能到的区间,再更新这一层实际能到的区间。
#include<bits/stdc++.h>
#define LL long long
#define INF INT64_MAX
#define MOD 1000000007
#define stree SegTree[f][root]
#define lson SegTree[f][root << 1]
#define rson SegTree[f][root << 1 | 1]
using namespace std;
typedef pair<int,int>pa;
const int N = 100005;
int SegTree[2][N*4], lz[2][N*4];
vector<int> v[N];
void Pushup(int root, int f){stree = lson+rson;}
void Pushdown(int root, int l, int r, int mid, int f)
{
if(lz[f][root]==-1) return;
lson = lz[f][root]*(mid-l+1);
rson = lz[f][root]*(r-mid);
lz[f][root<<1]=lz[f][root<<1|1]=lz[f][root];
lz[f][root]=-1;
}
void update(int root, int l, int r, int ul, int ur, int val, int f)
{
//printf("up l = %d, r = %d, root = %d\n", l, r, root);
if(l>=ul && r<=ur)
{
//printf("root = %d\n", root);
stree = (r-l+1)*val;
lz[f][root] = val;
return;
}
int mid = l+r>>1;
Pushdown(root, l, r, mid, f);
if(mid >= ul) update(root<<1, l, mid, ul, ur, val, f);
if(mid < ur) update(root<<1|1, mid+1, r, ul, ur, val, f);
Pushup(root, f);
//printf("up %d tr= %d\n",root, stree);
}
int query(int root, int l, int r, int ql, int qr, int f)
{
//printf("l = %d, r = %d, root = %d, stree = %d\n", l, r, root, stree);
if(!stree)
{
//printf("int root = %d, stree = %d\n", root, stree);
return INT_MAX;
}
if(l==r) return l;
int mid = l+r>>1;
Pushdown(root, l, r, mid, f);
if(l>=ql && r<=qr)
{
if(lson>0) return query(root<<1, l, mid, l, mid, f);
else return query(root<<1|1, mid+1, r, mid+1, r, f);
}
else
{
if(mid < ql) return query(root<<1|1, mid+1, r, ql, qr, f);
else if(mid >= qr) return query(root<<1, l, mid, ql, qr, f);
else return min(query(root<<1, l, mid, ql, mid, f), query(root<<1|1, mid+1, r, mid+1, qr, f));
}
}
int main()
{
int t, n, m, k, x, y;
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d", &n, &m, &k);
for(int i = 1;i <= n;i++) v[i].clear();
for(int i = 1;i <= k;i++)
{
scanf("%d%d", &x, &y);
v[x].push_back(y);
}
LL ans = 0;
for(int i = 1;i <= m*4;i++) SegTree[0][i]=SegTree[1][i]=0,lz[0][i]=lz[1][i]=-1;
update(1, 1, m, 1, 1, 1, 0);
for(int i = 1;i <= n;i++)
{
int l = 0;
sort(v[i].begin(), v[i].end());
for(auto it: v[i])
{
if(it-1>=l+1)
{
int pos = query(1, 1, m, l+1, it-1, i&1^1);
//printf("pos = %d, it = %d\n", pos, it);
if(pos!=INT_MAX) update(1, 1, m, pos, it-1, 1, i&1);
}
l = it;
}
if(l+1 <= m)
{
int pos = query(1, 1, m, l+1, m, i&1^1);
//printf("2 pos = %d, it = %d\n", pos, m);
if(pos!=INT_MAX) update(1, 1, m, pos, m, 1, i&1);
}
ans += SegTree[i&1][1];
//printf("ans = %lld\n", ans);
update(1, 1, m, 1, m, 0, i&1^1);
}
printf("%lld\n", ans);
}
return 0;
}