[ABC203E]White Pawn
[ABC203E]White Pawn
壹、题目描述 ¶
贰、题解 ¶
原来我的白兵会打架.
由于白兵会一直往下走,我们可以考虑对于列维护一个 “可用列” 集合。
对于同一行的黑兵,我们考虑有什么影响,假设当前的黑兵在第 \(j\) 列,那么:
- 如果 \(j\) 原来是可用的,那么它会被挡住;
- 如果 \(j-1\) 或者 \(j+1\) 原来可用,那么不管 \(j\) 原来是否可用,它现在一定是可用的;
我们将黑兵按照 \(x\) 为关键字排序,对于同一行的一起处理就行了。
注意删除和加入集合的先后顺序,可以在代码中看看。
叁、参考代码 ¶
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
#define NDEBUG
#include<cassert>
namespace Elaina{
#define rep(i, l, r) for(int i=(l), i##_end_=(r); i<=i##_end_; ++i)
#define drep(i, l, r) for(int i=(l), i##_end_=(r); i>=i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define mmset(a, b) memset(a, b, sizeof a)
#define siz(a) ((int)(a).size())
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template<class T>inline T fab(T x){ return x<0? -x: x; }
template<class T>inline void getmin(T& x, const T rhs){ x=min(x, rhs); }
template<class T>inline void getmax(T& x, const T rhs){ x=max(x, rhs); }
template<class T>inline T readin(T x){
x=0; int f=0; char c;
while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
return f? -x: x;
}
template<class T>inline void writc(T x, char s='\n'){
static int fwri_sta[1005], fwri_ed=0;
if(x<0) putchar('-'), x=-x;
do fwri_sta[++fwri_ed]=x%10, x/=10; while(x);
while(putchar(fwri_sta[fwri_ed--]^48), fwri_ed);
putchar(s);
}
}
using namespace Elaina;
const int maxm=2e5;
pii pawn[maxm+5];
int n, m;
inline void input(){
n=readin(1), m=readin(1);
rep(i, 1, m)
pawn[i].fi=readin(1), pawn[i].se=readin(1);
sort(pawn+1, pawn+m+1);
}
set<int>avai;
vector<int>rem, ins;
inline int saya(int x){
auto it=avai.find(x);
if(it!=avai.end() && (*it)==x) return 1;
return 0;
}
signed main()
{
input();
avai.insert(n);
for(int l=1, r; l<=m; l=r+1){
for(r=l; r<=m && pawn[r+1].fi==pawn[l].fi; ++r);
rep(i, l, r) rem.push_back(pawn[i].se);
rep(i, l, r){
if(saya(pawn[i].se-1) || saya(pawn[i].se+1))
ins.push_back(pawn[i].se);
}
// pay attention to the order
while(!rem.empty()) avai.erase(rem.back()), rem.pop_back();
while(!ins.empty()) avai.insert(ins.back()), ins.pop_back();
}
writc(siz(avai));
return 0;
}
肆、关键的地方 ¶
抓住关键 —— 我们一定会往下走。那么,对于同一行,我们就只需要考虑对于这一行以后的行的影响即可。