NOIP2023 双序列拓展

洛谷传送门

首先 x1=y1 显然不合法。若 x1>y1 就把 x,y 全部取相反数,这样就只用考虑 x1<y1 的情况了。

然后考虑一个 O(nmq) 的 dp,设 fi,j 为拓展 X 的前 i 个元素和 Y 的前 j 个元素是否可行。那么若 xi<yjfi,jfi1,j,fi,j1,fi1,j1 的或,否则 fi,j=0

发现这个 dp 的转移形式很像网格上行走,于是考虑转成网格上的问题。考虑令 ci,j=[xi<yj],那么可行当且仅当能找到一条从 (1,1)(n,m) 的全为 1八连通的路径。

注意到任意两行之间 1 的位置总是包含关系,这意味着不用考虑斜着走,即 (i1,j1) 走到 (i,j),因为可以被 (i1,j1)(i1,j)(i,j)(i1,j1)(i,j1)(i,j) 的其中一个代替。于是只用考虑四连通的路径。

考虑从特殊性质入手,即网格第 n 行和第 m 列全为 1(如果不全为 1 一定不可行),这样只要到达第 n 行或第 m 列就赢了。考虑递归求解,设 f(n,m) 为当前在 (1,1),是否能到达第 n 行或第 m 列。设 i=argmink=1n1{xk},j=argmaxk=1m1{yk}。若第 i 列全为 1 则可以直接递归至 f(i,m),若第 j 列全为 1 则可以直接递归至 f(n,j);若都不满足,则网格一定存在一个以 0 组成的十字架,把起点和终点隔开,于是这种情况直接返回不可行。所有要用到的信息都能预处理 x,y 的前缀 minmax 数组然后 O(1) 求出,所以复杂度为 O((n+m)q)

对于一般的情况,考虑设 u=argmink=1n{xk},v=argmaxk=1m{yk},那么第 u 行和第 v 列一定要全为 1。容易发现网格被第 u 行和第 v 列分成了左上角和右下角两个互相独立的部分,于是把右下角的部分翻转过来,做一遍同样的问题即可。

总时间复杂度就是 O((n+m)q)

code
#include <bits/stdc++.h>
#define fst first
#define scd second
#define pb emplace_back
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef double db;
typedef long double ldb;
inline int read() {
int x = 0;
bool f = 0;
char c = getchar();
while (c < '0' || c > '9') {
f |= (c == '-');
c = getchar();
}
while ('0' <= c && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return f ? -x : x;
}
const int maxn = 500100;
const int inf = 0x3f3f3f3f;
int n, m, q, test, a[maxn], b[maxn];
int c[maxn], d[maxn];
pii pcmn[maxn], pcmx[maxn], pdmn[maxn], pdmx[maxn];
pii scmn[maxn], scmx[maxn], sdmn[maxn], sdmx[maxn];
int dfs1(int x, int y) {
if (x == 1 || y == 1) {
return 1;
}
int p1 = pcmn[x - 1].scd, p2 = pdmx[y - 1].scd;
if (c[p1] < pdmn[y - 1].fst) {
return dfs1(p1, y);
} else if (pcmx[x - 1].fst < d[p2]) {
return dfs1(x, p2);
} else {
return 0;
}
}
int dfs2(int x, int y) {
if (x == n || y == m) {
return 1;
}
int p1 = scmn[x + 1].scd, p2 = sdmx[y + 1].scd;
if (c[p1] < sdmn[y + 1].fst) {
return dfs2(p1, y);
} else if (scmx[x + 1].fst < d[p2]) {
return dfs2(x, p2);
} else {
return 0;
}
}
inline int calc() {
if (c[1] == d[1]) {
return 0;
}
if (c[1] > d[1]) {
for (int i = 1; i <= n; ++i) {
c[i] = -c[i];
}
for (int i = 1; i <= m; ++i) {
d[i] = -d[i];
}
}
pcmn[0].fst = pdmn[0].fst = inf;
pcmx[0].fst = pdmx[0].fst = -inf;
for (int i = 1; i <= n; ++i) {
pcmn[i] = min(pcmn[i - 1], mkp(c[i], i));
pcmx[i] = max(pcmx[i - 1], mkp(c[i], i));
}
for (int i = 1; i <= m; ++i) {
pdmn[i] = min(pdmn[i - 1], mkp(d[i], i));
pdmx[i] = max(pdmx[i - 1], mkp(d[i], i));
}
scmn[n + 1].fst = inf;
sdmn[m + 1].fst = inf;
scmx[n + 1].fst = -inf;
sdmx[m + 1].fst = -inf;
for (int i = n; i; --i) {
scmn[i] = min(scmn[i + 1], mkp(c[i], i));
scmx[i] = max(scmx[i + 1], mkp(c[i], i));
}
for (int i = m; i; --i) {
sdmn[i] = min(sdmn[i + 1], mkp(d[i], i));
sdmx[i] = max(sdmx[i + 1], mkp(d[i], i));
}
int p1 = pcmn[n].scd, p2 = pdmx[m].scd;
for (int i = 1; i <= m; ++i) {
if (c[p1] >= d[i]) {
return 0;
}
}
for (int i = 1; i <= n; ++i) {
if (c[i] >= d[p2]) {
return 0;
}
}
return dfs1(p1, p2) && dfs2(p1, p2);
}
void solve() {
test = read();
n = read();
m = read();
q = read();
for (int i = 1; i <= n; ++i) {
a[i] = read();
}
for (int i = 1; i <= m; ++i) {
b[i] = read();
}
for (int i = 1; i <= n; ++i) {
c[i] = a[i];
}
for (int i = 1; i <= m; ++i) {
d[i] = b[i];
}
putchar('0' + calc());
while (q--) {
for (int i = 1; i <= n; ++i) {
c[i] = a[i];
}
for (int i = 1; i <= m; ++i) {
d[i] = b[i];
}
int kx, ky;
kx = read();
ky = read();
while (kx--) {
int x, y;
x = read();
y = read();
c[x] = y;
}
while (ky--) {
int x, y;
x = read();
y = read();
d[x] = y;
}
putchar('0' + calc());
}
putchar('\n');
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}

有小丑场上把

for (int i = 1; i <= n; ++i) {
c[i] = a[i];
}
for (int i = 1; i <= m; ++i) {
d[i] = b[i];
}

写成了

for (int i = 1; i <= n; ++i) {
c[i] = a[i];
d[i] = b[i];
}

暴挂 30 分,怎么会是呢。

posted @   zltzlt  阅读(315)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示