[ABC203E]White Pawn

[ABC203E]White Pawn

壹、题目描述 ¶

传送门 to Atcoder.

贰、题解 ¶

原来我的白兵会打架.

由于白兵会一直往下走,我们可以考虑对于列维护一个 “可用列” 集合。

对于同一行的黑兵,我们考虑有什么影响,假设当前的黑兵在第 \(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;
}

肆、关键的地方 ¶

抓住关键 —— 我们一定会往下走。那么,对于同一行,我们就只需要考虑对于这一行以后的行的影响即可。

posted @ 2021-06-03 16:57  Arextre  阅读(124)  评论(0编辑  收藏  举报