专栏文章
题解:CF2152F Triple Attack
CF2152F题解参与者 4已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @minplaz7
- 此快照首次捕获于
- 2025/12/02 06:16 3 个月前
- 此快照最后确认于
- 2025/12/02 06:16 3 个月前
我知道有人会说我非人哉但我还是要写这篇题解。
由于题目保证 单调不降,因此题意转化为选定区间内最大子集使得子集内所有下标差为 的元素的差大于 。
不难证明从第一个或最后一个数开始选,贪心地选中第一个/最后一个(与上面对应)能保持条件满足的元素是最优的。这里我们从第一个数开始选。
首先对于每个数 预处理其后第一个与其差大于 的元素位置,记为 。
接下来,我们定义一个状态为一个二元组 。每个二元组 有一个唯一的后继状态,若 ,则为 ;否则为 。实际上,一个“状态”代表的是一个合法子集的最后两个元素的位置。
由上述定义可知,将区间长度小于 的特殊情况判掉之后,查询 的答案即为最大的整数 使得状态 的 次后继状态中的两个元素均不大于 。
每次查询暴力进行上述操作显然无法通过此题,因此考虑使用
map 存储所有的 pair 进行记忆化搜索。然而提交之后会出现 TLE 的情况,因此考虑将 pair 编码为 long long,使用 unordered_map 存储所有编码并进行记忆化搜索,可以在 2.9s 内通过此题。时间复杂度未知。
这道题在我拥有前五道题的 AC 的基础上进一步扩大了我的优势,使我不仅在本次比赛中取得了 Master 更与 International Master 的距离更近了 左右。
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 条评论,欢迎与作者交流。
正在加载评论...