CF1379F2 Chess Strikes Back (hard version)

给$2n\times 2m$的网格,分成$nm$个$2\times 2$的网格,需要填左上角和右下角的某一个,询问是否可以填完之后没有角相同的格子。

有$q$次修改,禁止填或者恢复填。

  • 如果禁止右下角,发现左上方的部分都需要填在左上角。

  • 如果禁止左上角,发现右下方的部分都需要填在右下角。

我们设每行左边控制到$l[i]$,右边控制到$r[i]$。

考虑一行的情况,显然$l[i]\geq r[i]$,不成立。

考虑两行如果下面那行$l[i]\leq r[i]$,会发现顶点碰到了。

考虑那么这样就可以合并了。

维护区间的最大$l$,最小$r$,维护合并的是否可以填充。

一些小细节

  • 注意区间左右合并的大小判断。
  • 注意$set.begin(),set.rebegin()$
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

#include <bits/stdc++.h>
#include <set>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mk make_pair
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0', c = getchar();
return x * f;
}

const int SEN = 2e5 + 10;
int n, m;
struct segmentTree
{

int u[SEN << 2], d[SEN << 2], p[SEN << 2];
set<int> ri[SEN], le[SEN];
void pushup(int pos)
{
u[pos] = max(u[pos << 1], u[pos << 1 | 1]);
d[pos] = min(d[pos << 1], d[pos << 1 | 1]);
p[pos] = p[pos << 1] | p[pos << 1 | 1] | (d[pos << 1] <= u[pos << 1 | 1]);
}

void update(int x, int f, int w, int v, int pos, int l, int r)
{
if (l == r)
{
if (f == 1)
{
if (w)
ri[l].insert(v);
else
ri[l].erase(v);
}
else
{
if (w)
le[l].insert(v);
else
le[l].erase(v);
}
u[pos] = (ri[l].size() == 0 ? 0 : *ri[l].rbegin());
d[pos] = (le[l].size() == 0 ? m + 1 : *le[l].begin());
//cout << l << " " << v << " " << w << " " << u[pos] << ' ' << d[pos] << endl;
p[pos] = d[pos] <= u[pos];
return;
}
int mid = (l + r) >> 1;
if (x <= mid)
update(x, f, w, v, pos << 1, l, mid);
else
update(x, f, w, v, pos << 1 | 1, mid + 1, r);
pushup(pos);
}
void build(int pos, int l, int r)
{
u[pos] = 0;
d[pos] = m + 1;
if (l == r)
{
return;
}
int mid = (l + r) >> 1;
build(pos << 1, l, mid);
build(pos << 1 | 1, mid + 1, r);
}
} T;
map<pii, int> mp;
int main()
{
n = read(), m = read();
T.build(1, 1, n);
int q = read();
for (int i = 1; i <= q; i++)
{
int x = read(), y = read();
x++, y++;
if (mp[mk(x, y)] == 0)
{
mp[mk(x, y)] = 1;
if (x & 1)
T.update(x / 2, 1, 1, y / 2, 1, 1, n);
else
T.update(x / 2, 0, 1, y / 2, 1, 1, n);
}
else
{
mp[mk(x, y)] = 0;
if (x & 1)
T.update(x / 2, 1, 0, y / 2, 1, 1, n);
else
T.update(x / 2, 0, 0, y / 2, 1, 1, n);
}
//cout << T.u[1] << " " << T.d[1] << endl;
puts(T.p[1] ? "NO" : "YES");
}
}