抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

题目传送门

题意

有一个 \(n\times m\) 的黑白矩阵,初始时是全白的。有 \(q\) 次操作,每次操作形如 \(a_i,l_i,r_i\),表示把 \(a_i\) 行的 \(l_i\) 列到 \(r_i\) 列的格子反转颜色。

每次操作后,你要找出 \(x_1,y_1,x_2,y_2\),满足 \(x_1 < x_2,y_1 < y_2, col(x_1,y_1)=col(x_2,y_2),col(x_1,y_2)=col(x_2,y_1),col(x_1,y_1)\ne col(x_1,y_2)\)。若不存在则输出 \(-1\)

\(n,m\le 2000,q\le 5\times 10^5\)

题解

考虑如何判断是否有解。

\(S_i=\{j\mid col(i,j)=\text{black}\}\)。对于固定的两行 \(x_1,x_2\),有解的条件是 \(S_{x_1}\) 不是 \(S_{x_2}\) 的子集且 \(S_{x_2}\) 不是 \(S_{x_1}\) 的子集。

我们把这些集合按大小从小到大排序,若 \(S_1\subseteq S_2\subseteq S_3\subseteq\cdots\subseteq S_n\),则一定无解,否则一定存在一个 \(i\) 使得 \(S_{i}\) 不是 \(S_{i+1}\) 的子集,又因为是按集合大小从小到大排序的,\(S_{i+1}\) 也一定不是 \(S_i\) 的子集,那么这两行就是满足条件的。

然后考虑求出一组解,我们只要把所有满足条件的 \(i\) 都记下来。对于两个集合 \(S_{i},S_{i+1}\),其中一个 \(y\) 一定是在 \(S_{i}\) 中是黑色的但在 \(S_{i+1}\) 中是白色的,另一个 \(y\) 反之。

用 bitset 维护这些集合,然后用位运算和 _Find_First 函数即可求出 \(y_1,y_2\)

时间复杂度 \(O(q(\frac{m}{w}+\log n))\)

代码

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
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <bitset>
#include <set>
int read(){
register int x = 0;
register char ch = getchar(), f = 1;
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = !f;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0');
return f ? x : -x;
}
#define N 2005
int n, m, q, x1, _y1, x2, _y2;
std :: bitset<N> a[N], nw[N], tmp;
std :: set< std :: pair<int, int> > S, ans;
bool check(int i, int j){
return (a[i] & a[j]) != a[i];
}
void add(std :: pair<int, int> p){
if (check(p.first, p.second)) ans.insert(p);
}
void del(std :: pair<int, int> p){
if (check(p.first, p.second)) ans.erase(p);
}
void Erase(std :: pair<int, int> x){
int nx, i, pr;
auto it = S.lower_bound(x), tmp = it;
i = x.second, nx = (++tmp) -> second, pr = (--it) -> second;
del(std :: make_pair(pr, i)), del(std :: make_pair(i, nx)), add(std :: make_pair(pr, nx));
S.erase(x);
}
void Insert(std :: pair<int, int> x){
int nx, i, pr;
auto it = S.lower_bound(x);
i= x.second, nx = it -> second, pr = (--it) -> second;
add(std :: make_pair(pr, i)), add(std :: make_pair(i, nx)), del(std :: make_pair(pr, nx));
S.insert(x);
}
int main(){
n = read(), m = read(), q = read();
nw[1] = 1;
for (register int i = 2; i <= m; ++i) nw[i] = nw[i - 1] << 1 | nw[1];
a[n + 1] = nw[m], S.insert(std :: make_pair(0, 0));
for (register int i = 1; i <= n; ++i) S.insert(std :: make_pair(0, i));
S.insert(std :: make_pair(m, n + 1));
for (register int i = 1; i <= q; ++i){
int k = read(), l = read(), r = read();
Erase(std :: make_pair(a[k].count(), k));
a[k] ^= nw[r - l + 1] << (l - 1);
Insert(std :: make_pair(a[k].count(), k));
if (ans.empty()) printf("-1\n");
else{
x1 = ans.begin() -> first, x2 = ans.begin() -> second;
_y1 = ((a[x1] ^ a[x2]) & a[x1])._Find_first(), _y2 = ((a[x1] ^ a[x2]) & a[x2])._Find_first();
if (x1 > x2) std :: swap(x1, x2);
if (_y1 > _y2) std :: swap(_y1, _y2);
printf("%d %d %d %d\n", x1, _y1 + 1, x2, _y2 + 1);
}
}
}

评论