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;
}