CF1379F2 Chess Strikes Back (hard version)
CF1379F2 Chess Strikes Back (hard version)
究极无敌超有趣线段树!
把整个棋盘分成 \(n \times m\) 个 \(2 \times 2\) 的大方格,不难发现每个大格子必须有一个格子放国王。
可以发现有四种大方格:
1、两个白格都可用。
2、只有左上角可用,记左上角格子为 \(a\)。
3、只有右下角可用,记左上角格子为 \(b\)。
4、两个白格都不可用。若存在则没有可行方案。
发现当存在 \(a\) 在相邻 \(b\) 的右边或右下角,则不可行。
进一步推广,发现不存在可行方案当且仅当:存在一个 \(a\) 在 \(b\) 的右下方(只要横纵坐标都大于即可)
考虑线段树维护。把整个棋盘先压成 \(n \times m\) 的大方格棋盘,然后对行建树,记录每一行列数最小的 \(b\) 和列数最大的 \(a\),分别记作 \(mn_i\) 和 \(mx_i\)(用 set 维护),然后在线段树上维护 \(mn_i\) 的前缀最小和 \(mx_i\) 的后缀最大。最后只需要判断存不存在较上部分的前缀最小 \(\lt\) 较下部分的后缀最大即可。时间复杂度 \(O(n\log n)\)。
至于影响可撤销,其实只需要开个 map 记录一下就可以了。
#include<bits/stdc++.h>
#define F(i, l, r) for(int i(l); i <= (r); ++ i)
#define G(i, r, l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 3e5;
const int inf = 1e9;
char buf[100], *p1 = buf, *p2 = buf;
inline int gc(){ return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++; }
inline int rd(){
int x = 0; char ch;
while(!isdigit(ch = gc()));
do x = (x << 3) + (x << 1) + (ch ^ 48); while(isdigit(ch = gc()));
return x;
}
set<int> a[N], b[N];
map<pair<int, int>, int>mp;
int tag[N * 4], mx[N * 4], mn[N * 4];
int n, m, Q;
void pushup(int u){
mx[u] = max(mx[u * 2], mx[u * 2 + 1]);
mn[u] = min(mn[u * 2], mn[u * 2 + 1]);
if(tag[u * 2] || tag[u * 2 + 1]) tag[u] = 1;
else if(mn[u * 2] <= mx[u * 2 + 1]) tag[u] = 1;
else tag[u] = 0;
}
void build(int u, int l, int r){
if(l == r) {
mx[u] = 0;
mn[u] = inf;
tag[u] = 0;
return ;
}
int mid = (l + r) / 2;
build(u * 2, l, mid);
build(u * 2 + 1, mid + 1, r);
pushup(u);
}
void update(int u, int l, int r, int x){
if(l == r){
mx[u] = *a[l].rbegin();
mn[u] = *b[l].begin();
if(mn[u] <= mx[u]) tag[u] = 1;
else tag[u] = 0;
return ;
}
int mid = (l + r) / 2;
if(x <= mid) update(u * 2, l, mid, x);
else update(u * 2 + 1, mid + 1, r, x);
pushup(u);
}
signed main(){
n = rd(), m = rd(), Q = rd();
F(i, 1, n){
a[i].insert(0);
b[i].insert(inf);
}
build(1, 1, n);
while(Q --){
int x = rd() + 1, y = rd() + 1;
pair<int, int> o = make_pair(x, y);
if(x % 2 == 1){
if(mp[o]== 0){
a[x / 2].insert(y / 2);
mp[o] = 1;
}
else{
a[x / 2].erase(y / 2);
mp[o] = 0;
}
}
else{
if(mp[o] == 0){
b[x / 2].insert(y / 2);
mp[o] = 1;
}
else{
b[x / 2].erase(y / 2);
mp[o] = 0;
}
}
update(1, 1, n, x / 2);
if(!tag[1]){
puts("YES");
}
else{
puts("NO");
}
}
return fflush(0), 0;
}

浙公网安备 33010602011771号