首页 > 其他分享 >NOIP2023 双序列拓展

NOIP2023 双序列拓展

时间:2023-11-27 22:23:04浏览次数:28  
标签:typedef int 网格 拓展 read long 序列 NOIP2023 define

洛谷传送门

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

然后考虑一个 \(O(nmq)\) 的 dp,设 \(f_{i, j}\) 为拓展 \(X\) 的前 \(i\) 个元素和 \(Y\) 的前 \(j\) 个元素是否可行。那么若 \(x_i < y_j\) 则 \(f_{i, j}\) 取 \(f_{i - 1, j}, f_{i, j - 1}, f_{i - 1, j - 1}\) 的或,否则 \(f_{i, j} = 0\)。

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

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

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

对于一般的情况,考虑设 \(u = \operatorname{argmin}_{k = 1}^n\{x_k\}, v = \operatorname{argmax}_{k = 1}^m\{y_k\}\),那么第 \(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\) 分,怎么会是呢。

标签:typedef,int,网格,拓展,read,long,序列,NOIP2023,define
From: https://www.cnblogs.com/zltzlt-blog/p/17860654.html

相关文章

  • NOIP2023 游记
    Day0打摆。打摆。打摆。看tarjan。打摆。打摆。打摆。Day1早上很早到了附中,发现准考证上没有照片,黑糊糊一片,被教练强行紧急更换了一个,感觉不换其实也没什么关系。进考场,发现在最后一排,旁边不认识,前面不认识,前面的旁边不认识,sad。然后发密码,开T1,发现会了,15min写完......
  • Weblogic < 10.3.6 'wls-wsat' XMLDecoder 反序列化漏洞(CVE-2017-10271)
    Weblogic<10.3.6'wls-wsat'XMLDecoder反序列化漏洞(CVE-2017-10271)Weblogic的WLSSecurity组件对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令。环境搭建cdweblogic/CVE-2017-10271docker-compose......
  • 聪明办法学Python-2023-task04&拓展01
    参考视频链接:【条件】聪明办法学Python第二版_哔哩哔哩_bilibili​优雅代码编写指北_哔哩哔哩_bilibilitask04if语句ifstatementConditionalsMakeDecisionsif语句流程判断成立不成立一个例子:deff(x):print("A",end="")......
  • C# Json序列化的格式化问题
    问题来源: 客户要求传送给他的JSON文件的float型格式化为2位小数,数值型有30-40个栏位,一个一个修改也不是很好.bing和百度找到的方式都是自己定义一个JsonConverter,进行格式化.找到的都是在字符串两边加++的例子,核心转化的代码如下:classStringFormatConverter:JsonCo......
  • 数据类型拓展
    整数拓展:进制二进制0b;八进制0;十进制;十六进制0x 十进制转二进制,将正的十进制除以二,得到商后再除以二,直到商为1或0时,然后各部余数填1,整数填0,然后倒着写出来,最后高位补零一个正的二进制的数转为负的只需要将该数的二进制码取反然后+1(补码)即可浮点拓展:浮点数一般都会存在舍入误差,所以......
  • LeetCode 354. (经典问题) 俄罗斯套娃信封问题 (俄罗斯套娃模型 + 最长下降子序列
    packageleetcode;importjava.util.Arrays;publicclasslec154{/***首先是思路来源:https://leetcode.cn/problems/russian-doll-envelopes/solutions/19681/zui-chang-di-zeng-zi-xu-lie-kuo-zhan-dao-er-wei-er/*思路:先按照宽度降序(升序)接着......
  • 试题 D: 本质上升序列(C/C++)
    题目描述:小蓝特别喜欢单调递增的事物。在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。例如,在字符串lanqiao中,如果取出字符n和q,则nq组成一个单调递增子序列。类似的单调递增子序列还有lnq......
  • 使用skforecast进行时间序列预测
    时间序列预测是数据科学和商业分析中基于历史数据预测未来价值的一项重要技术。它有着广泛的应用,从需求规划、销售预测到计量经济分析。由于Python的多功能性和专业库的可用性,它已经成为一种流行的预测编程语言。其中一个为时间序列预测任务量身定制的库是skforecast。在本文中,将......
  • 数据分享|Eviews用ARIMA、指数曲线趋势模型对中国进出口总额时间序列预测分析
    全文链接:https://tecdat.cn/?p=34361原文出处:拓端数据部落公众号研究的背景及意义众自20世纪80年代至今,随着改革开放的深入以及中国最终加入WTO,我国的对外贸易实现了跨越式的发展,中国已经成为世界第一大出口国和第二大进口国,中国经济对世界经济做出了重大贡献。与此同时,中国经......
  • PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子|附代码数据
    全文下载链接:http://tecdat.cn?p=26519最近我们被客户要求撰写关于LSTM的研究报告,包括一些图形和统计输出。一个简单的编码器-解码器LSTM神经网络应用于时间序列预测问题:预测天然气价格,预测范围为10天。“进入”时间步长也设置为10天。)只需要10天来推断接下来的10天。......