首页 > 其他分享 >B - Arithmetic Progression Subsequence

B - Arithmetic Progression Subsequence

时间:2024-01-22 18:55:39浏览次数:32  
标签:满足条件 Progression 10 int cdot Sample leq Subsequence Arithmetic

B - Arithmetic Progression Subsequence

Problem Statement

You are given a sequence $A$ of length $N$ consisting of integers between $1$ and $\textbf{10}$, inclusive.

A pair of integers $(l,r)$ satisfying $1\leq l \leq r\leq N$ is called a good pair if it satisfies the following condition:

  • The sequence $(A_l,A_{l+1},\ldots,A_r)$ contains a (possibly non-contiguous) arithmetic subsequence of length $3$. More precisely, there is a triple of integers $(i,j,k)$ with $l \leq i < j < k\leq r$ such that $A_j - A_i = A_k - A_j$.

Find the number of good pairs.

Constraints

  • $3 \leq N \leq 10^5$
  • $1\leq A_i \leq 10$
  • All input numbers are integers.

Input

The input is given from Standard Input in the following format:

$N$
$A_1$ $\ldots$ $A_N$

Output

Print the answer.


Sample Input 1

5
5 3 4 1 5

Sample Output 1

3

There are three good pairs: $(l,r)=(1,4),(1,5),(2,5)$.

For example, the sequence $(A_1,A_2,A_3,A_4)$ contains an arithmetic subsequence of length $3$, which is $(5,3,1)$, so $(1,4)$ 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 了我是不可能想到的。

  事实上不满足条件的数对 $(l,r)$ 的长度(即 $r-l+1$)一定不超过 $20$。因为 $1 \leq a_i \leq 10$,由鸽巢原理知道如果某个 $(l,r)$ 的长度超过 $20$,那么必然存在某个值出现了至少 $3$ 次,此时把这个值的 $3$ 个下标作为 $(i,j,k)$ 那么一定有 $a_j - a_i = a_k - a_j = 0$。即如果 $(l,r)$ 的长度超过 $20$,那么这些数对一定是满足条件的。因此我们只需枚举所有长度不超过 $20$ 的数对,并判断是否存在满足条件的 $(i,j,k)$ 即可,时间复杂度大概是 $O(10^2 \cdot n)$。

  下面给出更容易想到的做法。其实看到这个数据范围就知道做法肯定与值域有关。

  枚举 $(l,r)$ 中的 $r$,然后判断在 $[1,r]$ 中是否存在满足条件的 $(i,j,k)$。暴力的思路就是把所有满足条件的 $(i,j,k)$ 找出来,并找到当中 $i$ 的最大值,记作 $t$。那么以 $r$ 为右端点且满足条件的数对数量就是 $t$。暴力求肯定会超时,而且也不容易想到如何用值域来优化。

  因此想到能否预处理出每个前缀中满足条件的 $(i,j,k)$ 的 $i$ 的最大值。把所有满足条件的 $(i,j,k)$ 按照 $j$ 分成 $n$ 类,对于每个 $j$,我们不枚举下标,而是枚举值 $1 \leq a_i \leq 10$,$1 \leq a_k \leq 10$。如果满足 $a_j - a_i = a_k - a_j$,那么我们应该找到在 $[1, j-1]$ 中是否存在值 $a_i$,如果存在则选择最大下标。同理在 $[j+1, n]$ 中是否存在值 $a_k$,如果存在则选择最小下标(贪心,显然 $k$ 越小则能被更多的 $(l,r)$ 包含)。如果都存在,我们令 $f(R_{j+1,a_k}) = \min\{ f(R_{j+1,a_k}), \, L_{j-1, a_i} \}$。其中 $L_{j-1, a_i}$ 是 $[1, j-1]$ 中值 $a_i$ 出现的最大下标,$R_{j+1, a_k}$ 是 $[j+1, n]$ 中值 $a_k$ 出现的最小下标,这两个都可以通过 $O(10 \cdot n)$ 的复杂度预处理出来。$f(x)$ 则表示所有满足条件且 $k=x$ 的 $(i,j,k)$ 中,$i$ 的最小值。

  上面预处理的时间复杂度是 $O(10^2 \cdot n)$,当然还可以优化到 $O(10 \cdot n)$,即只枚举 $a_i$,$a_k$ 通过 $a_k = 2 \cdot a_i - a_j$ 得到,只需判断是否满足 $1 \leq a_k \leq 10$ 即可。

  最后由于求的是前缀中 $i$ 的最小值,只需从左到右遍历令 $f(i) = \min\{ f(i), f(i-1) \}$ 即可。

  AC 代码如下,时间复杂度为 $O(10 \cdot n)$:

#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

标签:满足条件,Progression,10,int,cdot,Sample,leq,Subsequence,Arithmetic
From: https://www.cnblogs.com/onlyblues/p/17980748

相关文章

  • CF1921 F Sum of Progression 题解
    QuestionCF1921FSumofProgression给定一个序列\(\{a\}\),有\(q\)组询问,对于每组询问\(s,d,k\),求\[a_s+a_{s+d}\cdot2+\cdots+a_{s+d(k-1)}\cdotk\]Solution\(s,d,k\)其实就是在描述一个等差数列考虑到\(d\timesk\len\)如果\(d\)很大,那么就意味着\(k\)很......
  • F. Sum of Progression
    F.SumofProgressionYouaregivenanarray$a$of$n$numbers.Therearealso$q$queriesoftheform$s,d,k$.Foreachquery$q$,findthesumofelements$a_s+a_{s+d}\cdot2+\dots+a_{s+d\cdot(k-1)}\cdotk$.Inotherwords,foreach......
  • CF1921F Sum of Progression
    题目链接:CF一道经典的类型题,把这种类型的题拿出来单独说一下。注意到问题中涉及到需要维护\(a_{x+k\timesstep}\)这样的信息,这样的信息很难用树型结构维护,比较容易用块级结构维护,我们注意到其实是每次这种步长\(+step\)的信息很难维护,我们考虑一类特殊的分块:如果\(step\)......
  • Largest Subsequence
    操作:选取词性最大的子序列,向右循环一次问你进行多少次这样的操作能使数组有序,如果不能就输出-1思路:首先要知道的是一个词性最大的序列整个右移过后,数组的新词性最大的序列就是之前的词性最大序列去了最后一个字母.找出词性最大的子序列intn; strings......
  • [ABC271E] Subsequence Path 题解
    [ABC271E]SubsequencePath题解思路解析很好的一道题,很有迷惑性,表面上是一道图论实际上是dp,定义\(f_{i}\)为从\(1\)到\(i\)的最短“好路”。先把每条边对应的起点,终点和边权记录下来,然后输入每个\(e\),由于是子序列顺序不会改变,因此可以顺序进行操作。对于每一个\(e......
  • CF1621G Weighted Increasing Subsequences
    CF1621GWeightedIncreasingSubsequences你有一个长度为\(n\)的序列,定义\(a\)的一个长度为\(k\)的子序列为\(a_{i_1},a_{i_2},\dots,a_{i_k}\)。由此,我们不难发现,\(a\)的一个长度为\(k\)的子序列为上升子序列,当且仅当\(\forallj\in[1,k)\),\(a_{i_j}<a_{i_{j+1}}\)......
  • [Codeforces] CF1817A Almost Increasing Subsequence
    CF1817AAlmostIncreasingSubsequence题意给定长度为\(n\)一个序列\(a\)以及\(q\)次询问,每次询问给出\(l\)和\(r\),找出序列\(a\)在\([l,r]\)内最长的几乎递增子序列。对于几乎递增的定义:如果一个序列中不存在连续的三个数\(x\),\(y\),\(z\),使得\(x\gey\ge\......
  • CF571E Geometric Progressions
    CF571EGeometricProgressions洛谷:CF571EGeometricProgressionsCodeforces:CF571EGeometricProgressionsProblem给定\(n\)以及\(n\)个正整数对\(a_i,b_i\)。第\(i\)对\(a_i,b_i\)确定了一个序列\(\{a_i,a_ib_i,a_ib_i^2,a_ib_i^3,\ldots\}\)。询问......
  • [ARC133B] Dividing Subsequence
    DividingSubsequence这道题与最长公共子序列类似,可以先去水一水那道题。题意本题就是让你从\(p\)里面选出一个子序列\(b_i\)和\(q\)里面选出一个子序列\(a_i\),我们要使\(b_i\)是\(a_i\)的倍数。解法本题直接用动态规划,是\(O(n^2)\)做法,会超时,因此我们用树状数......
  • [CF83E] Two Subsequences 题解
    [CF83E]TwoSubsequences题解思路定义\(overlap(a,b)\)为字符串\(a\)的后缀与\(b\)的前缀的最大相等的长度,有\(|f(a,b)|=|a|+|b|-overlap(a,b)\),下文称匹配为相邻两串的\(overlap\)。观察到每次操作之后,一定有一个序列是以\(a_i\)为结尾的。所以根据这个......