abc179f

abc179f

大意

给定一个 \(n*n\) 的棋盘,中间 \((n-2)*(n-2)\) 的区域有黑色棋子。右边缘和下边缘总共长度为 \(2n-1\) 的区域有白色棋子。

有如下操作:

\((1,x)\) 表示从 \((1,x)\) 开始向下延伸,将所经过的黑色棋子变为白色,直到遇到第一个白色棋子停下。

\((2,x)\) 表示从 \((x,1)\) 开始向右延伸,将所经过的黑色棋子变为白色,直到遇到第一个白色棋子停下。

\((2\leq x \leq n-1)\)

问,进行q次给定操作后,黑色棋子有多少个(保证任意操作不重复)。

思路

比前两道题简单...

\(s_1\) 为当前所有 \((1,x)\)\(x\) 的最小值, \(s_2\) 同理记为另一种操作的最小值。

\(A\) 为之前所有的 \(s_1\) 值组成的序列, \(B\) 同理。

\(C\) 为之前 \(A\) 加入新元素时加入的一个特殊值组成的序列, \(D\) 同理。

假设本次操作为 \((1,x)\)

\(x < s_1\) ,不难发现,会有 \((s_2-2)\) 个棋子变为白色,因为形成 \(s_2\) 的操作形成了一道横屏障,仅有 \((2,s_2-1)\) 的棋子可以被选择 。

其实,该步操作之后,对于所有 \((1,x_i)\ ;\ x < x_i < s_1\) 其能选择的黑色棋子数一定是 \((s_2-2)\) ,因为选择 \(x\) 的操作形成了一道竖屏障。

所以我们在 \(A\) 中添加 \(s_1\) ,在 \(C\) 中添加 \((s_2-2)\) ,并更新 \(s_1 = x\)

\(x > s_1\) ,显然,按上述操作 \(A\) 一定是一个单调递减序列,且 \(A,B\) 中一一对应。

所以考虑在 \(A\) 中二分 \(x\)

对于另一种操作,思路与这种操作并无不同。

细节也是不少的...

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)

const int mod = 998244353;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;

ll n, q;
int qu[2][200200], cnt[2];
int num[2][200200];

int main() {
    cin >> n >> q;
    ll ans = (n-2) * (n-2);
    int a, x;
    ll s[2] = {n, n};
    for(int i=1; i<=q; i++) {
        cin >> a >> x;
        a--;
        int key = upper_bound(qu[a]+1, qu[a]+cnt[a]+1, x, greater< int >()) - qu[a];
        if(key > cnt[a]) {
            ans -= (s[a^1]-2);
            s[a] = x;
            qu[a][++cnt[a]] = x;
            num[a][cnt[a]] = s[a^1] - 2;
        } else ans -= num[a][key];
    }
    cout << ans;
    return 0;
}
posted @ 2020-11-09 20:51  ullio  阅读(130)  评论(0编辑  收藏  举报