CF1076G Array Game
CF1076G Array Game
手推出大半,不会实现。
记必胜点表示走到此点时,下一手必胜;必败点同理。
每人都想要对方走到必胜点自己走到必败点。
有一种想法。
记 表示 后缀第一个奇数的位置。
容易发现,对于询问 , 为必败点, 为必胜点。
由于最多可前进 格,那么 为必胜点。
那么转化为谁先让 为 谁赢,即如果 为偶格,为必胜点,否则为必败点。
就是操作 谁必胜。
但是这样极其难修改,考虑根据上述启发必胜态到必败态或者反过来的转移。
偶格必为必胜点,因为如果后面 格有必败点可直接过去,否则全为必胜点就在原地不动,让对手到将棋移到必胜点。
奇格必胜,当且仅当可移到必败,显然此时不动不是最优的选择,因为奇偶性变了。
只需要知道每个点可移到的第一个必败点的位置,只有 种不同取值。
然后考虑分块,记录在块的右端点的首个必败点距离确定时,走到块的左端点的首个必败点的距离。
预处理,对于每个值,处理 种不同取值即可。
考虑修改,加偶数不改变奇偶性,加奇数则为区间翻转。
顺便记录一下区间翻转后的答案覆盖即可。
时间复杂度大致是 ,带个 的小常数。
#include <cstdio>
typedef long long ll;
#define ha putchar(' ')
#define he putchar('\n')
inline int read() {
int x = 0;
char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x;
}
#define js(l, r, fail, tg, fl) for (int j = r; j >= l; --j) if ((fl ^ (!(a[j] ^ tg))) || fail <= m) fail++; else fail = 1;
inline int min(int x, int y)
{
return x < y ? x : y;
}
const int _ = 2e5 + 10, BL = 50, S = _ / BL + 10;;
int n, m, q, a[_], bel[_], L[S], R[S], f[2][S][7];
bool rev[S];
void build(int id) {
for (int i = 1; i <= m + 1; ++i) {
f[0][id][i] = f[1][id][i] = i;
js(L[id], R[id], f[0][id][i], 0, 0);
js(L[id], R[id], f[1][id][i], 0, 1);
f[0][id][i] = min(f[0][id][i], m + 1), f[1][id][i] = min(f[1][id][i], m + 1);
}
}
signed main() {
n = read(), m = read(), q = read();
for (int i = 1; i <= n; ++i) a[i] = read() & 1ll, bel[i] = (i - 1) / BL + 1;
for (int i = 1; i <= bel[n]; ++i) L[i] = R[i - 1] + 1, R[i] = i * BL;
R[bel[n]] = n;
for (int i = 1; i <= bel[n]; ++i) build(i);
int opt, l, r, c;
while (q--) {
opt = read(), l = read(), r = read();
if (opt == 1) {
c = read() & 1ll;
if (!c) continue;
if (bel[l] == bel[r]) {
for (int i = l; i <= r; ++i) a[i] ^= 1;
build(bel[l]);
continue;
}
for (int i = l; i <= R[bel[l]]; ++i) a[i] ^= 1;
build(bel[l]);
for (int i = bel[l] + 1; i <= bel[r] - 1; ++i) rev[i] ^= 1;
for (int i = L[bel[r]]; i <= r; ++i) a[i] ^= 1;
build(bel[r]);
} else {
int fail = m + 1;
if (bel[l] == bel[r]) {
js(l, r, fail, rev[bel[l]], 0);
putchar(fail == 1 ? '2' : '1'), he;
continue;
}
js(L[bel[r]], r, fail, rev[bel[r]], 0);
fail = min(fail, m + 1);
for (int i = bel[r] - 1; i >= bel[l] + 1; --i)
fail = f[rev[i]][i][fail];
js(l, R[bel[l]], fail, rev[bel[l]], 0);
fail = min(fail, m + 1);
putchar(fail == 1 ? '2' : '1'), he;
}
}
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18121967