专栏文章

题解:CF2152F Triple Attack

CF2152F题解参与者 4已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@minplaz7
此快照首次捕获于
2025/12/02 06:16
3 个月前
此快照最后确认于
2025/12/02 06:16
3 个月前
查看原文
我知道有人会说我非人哉但我还是要写这篇题解。
由于题目保证 xx 单调不降,因此题意转化为选定区间内最大子集使得子集内所有下标差为 22 的元素的差大于 zz
不难证明从第一个或最后一个数开始选,贪心地选中第一个/最后一个(与上面对应)能保持条件满足的元素是最优的。这里我们从第一个数开始选。
首先对于每个数 xix_i 预处理其后第一个与其差大于 zz 的元素位置,记为 tit_i
接下来,我们定义一个状态为一个二元组 (a,b)(a,b)。每个二元组 (a,b)(a,b) 有一个唯一的后继状态,若 ta=bt_a=b,则为 (b,ta+1)(b,t_a+1);否则为 (b,ta)(b,t_a)。实际上,一个“状态”代表的是一个合法子集的最后两个元素的位置。
由上述定义可知,将区间长度小于 33 的特殊情况判掉之后,查询 (l,r)(l,r) 的答案即为最大的整数 y+2y+2 使得状态 (l,l+1)(l,l+1)yy 次后继状态中的两个元素均不大于 rr
每次查询暴力进行上述操作显然无法通过此题,因此考虑使用 map 存储所有的 pair 进行记忆化搜索。然而提交之后会出现 TLE 的情况,因此考虑将 pair 编码为 long long,使用 unordered_map 存储所有编码并进行记忆化搜索,可以在 2.9s 内通过此题。
时间复杂度未知。
这道题在我拥有前五道题的 AC 的基础上进一步扩大了我的优势,使我不仅在本次比赛中取得了 Master 更与 International Master 的距离更近了 6060 左右。
C
// #define Redshift_Debug
#ifdef Redshift_Debug
#define debug(...) fprintf(stderr, __VA_ARGS__)
#include <chrono>
#else
#define debug(...)
#endif
#include <array>
#include <iostream>
#include <unordered_map>
#include <utility>
using namespace std;
const int N = 2.5e5 + 10, B = 20;
int n, z, q, a[N], nxt[N];
using pii = pair<int, int>;
using sta = array<pii, B>;
using ll = long long;
ll rmp(pii x)
{
	return 1ll * (x.first - 1) * n + x.second;
}
unordered_map<ll, sta> mp;
void init_global()
{
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
}

void init_local()
{
	mp.clear();
	cin >> n >> z;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
}
void dfs(int x, int y)
{
	if (mp.count(rmp(pii{x, y})))
		return;
	if (nxt[x] + (y == nxt[x]) > n)
	{
		for (auto &i : mp[rmp(pii{x, y})])
			i = {n + 1, n + 1};
		return;
	}
	int tnxt = nxt[x] + (y == nxt[x]);
	dfs(y, tnxt);
	mp[rmp(pii{x, y})][0] = pii{y, tnxt};
	for (int i = 1; i < B; i++)
	{
		mp[rmp(pii{x, y})][i] = mp[rmp(mp[rmp(pii{x, y})][i - 1])][i - 1];
	}
}
void run()
{
	for (int i = 1, j = 1; i <= n; i++)
	{
		while (j <= n and a[j] - a[i] <= z)
			j++;
		nxt[i] = j;
	}
	for (auto &i : mp[rmp(pii{n + 1, n + 1})])
		i = pii{n + 1, n + 1};
	cin >> q;
	for (int i = 1, l, r, res; i <= q; i++)
	{
		cin >> l >> r;
		if (r - l + 1 <= 2)
		{
			cout << r - l + 1 << '\n';
			continue;
		}
		dfs(l, l + 1);
		res = 2;
		pii buf = {l, l + 1};
		for (int i = B - 1; ~i; i--)
		{
			if (mp[rmp(buf)][i].second > r)
				continue;
			res += (1 << i);
			buf = mp[rmp(buf)][i];
		}
		cout << res << '\n';
	}
}
int main()
{
#ifdef Redshift_Debug
	auto st = chrono::high_resolution_clock::now();
#endif
	int T = 1;
	init_global();
	cin >> T;
	while (T--)
	{
		init_local();
		run();
	}
#ifdef Redshift_Debug
	auto ed = chrono::high_resolution_clock::now();
	fprintf(stderr, "%.9lf\n", (ed - st).count() / 1e9);
#endif
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...