B - Arithmetic Progression Subsequence
B - Arithmetic Progression Subsequence
Problem Statement
You are given a sequence of length consisting of integers between and , inclusive.
A pair of integers satisfying is called a good pair if it satisfies the following condition:
- The sequence contains a (possibly non-contiguous) arithmetic subsequence of length . More precisely, there is a triple of integers with such that .
Find the number of good pairs.
Constraints
- All input numbers are integers.
Input
The input is given from Standard Input in the following format:
Output
Print the answer.
Sample Input 1
5
5 3 4 1 5
Sample Output 1
3
There are three good pairs: .
For example, the sequence contains an arithmetic subsequence of length , which is , so is a good pair.
Sample Input 2
3
1 2 1
Sample Output 2
0
There may be cases where no good pairs exist.
Sample Input 3
9
10 10 1 3 3 7 2 2 5
Sample Output 3
3
解题思路
唉昨晚爆 0 了。先提一下官方给出的做法,太 trick 了我是不可能想到的。
事实上不满足条件的数对 的长度(即 )一定不超过 。因为 ,由鸽巢原理知道如果某个 的长度超过 ,那么必然存在某个值出现了至少 次,此时把这个值的 个下标作为 那么一定有 。即如果 的长度超过 ,那么这些数对一定是满足条件的。因此我们只需枚举所有长度不超过 的数对,并判断是否存在满足条件的 即可,时间复杂度大概是 。
这个思想与 B. Diverse Substrings 是一样的。
下面给出更容易想到的做法。其实看到这个数据范围就知道做法肯定与值域有关。
枚举 中的 ,然后判断在 中是否存在满足条件的 。暴力的思路就是把所有满足条件的 找出来,并找到当中 的最大值,记作 。那么以 为右端点且满足条件的数对数量就是 。暴力求肯定会超时,而且也不容易想到如何用值域来优化。
因此想到能否预处理出每个前缀中满足条件的 的 的最大值。把所有满足条件的 按照 分成 类,对于每个 ,我们不枚举下标,而是枚举值 ,。如果满足 ,那么我们应该找到在 中是否存在值 ,如果存在则选择最大下标。同理在 中是否存在值 ,如果存在则选择最小下标(贪心,显然 越小则能被更多的 包含)。如果都存在,我们令 。其中 是 中值 出现的最大下标, 是 中值 出现的最小下标,这两个都可以通过 的复杂度预处理出来。 则表示所有满足条件且 的 中, 的最小值。
上面预处理的时间复杂度是 ,当然还可以优化到 ,即只枚举 , 通过 得到,只需判断是否满足 即可。
最后由于求的是前缀中 的最小值,只需从左到右遍历令 即可。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N];
int l[N][11], r[N][11];
int f[N];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 10; j++) {
l[i][j] = l[i - 1][j];
if (a[i] == j) l[i][j] = i;
}
}
for (int i = n; i; i--) {
for (int j = 1; j <= 10; j++) {
r[i][j] = r[i + 1][j];
if (a[i] == j) r[i][j] = i;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 10; j++) {
int k = 2 * a[i] - j;
if (k < 1 || k > 10) continue;
if (l[i - 1][j] && r[i + 1][k]) f[r[i + 1][k]] = max(f[r[i + 1][k]], l[i - 1][j]);
}
}
for (int i = 1; i <= n; i++) {
f[i] = max(f[i], f[i - 1]);
}
LL ret = 0;
for (int i = 1; i <= n; i++) {
ret += f[i];
}
printf("%lld", ret);
return 0;
}
参考资料
Editorial - AtCoder Regular Contest 170:https://atcoder.jp/contests/arc170/editorial/9148
Submission #49545473 - AtCoder Regular Contest 170:https://atcoder.jp/contests/arc170/submissions/49545473
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17980748
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-01-22 Minimum Cost to Split an Array
2023-01-22 B. Emordnilap
2023-01-22 C. Quiz Master