#843. 等差数列

题目链接

#843. 等差数列

题目描述

给定一个大小为\(n\)的集合\(\{S\}\), 你可以从中挑选若干个数组成等差数列, 求最长的等差数列长度

输入描述

一行一个整数\(n\leq 5000\)

接下来一行\(n\)个整数\(|S_i| < {2^{31}}\), 描述集合\(\{S\}\)中的元素

输出描述

一行一个整数, 描述最长的等差数列的长度

样例输入

10
14 1 3 5 6 8 9 10 12 13 

样例输出

5

样例解释

等差数列包括(仅包括两项的不列举)

1 3 5

1 5 9 13

3 6 9 12

3 8 13

5 9 13

6 8 10 12 14

其中6 8 10 12 14最长,长度为5。

解题思路

dp

  • 状态表示:\(f[i][j]\) 表示后等差数列后两项为 \(a[j]\)\(a[i]\) 时的最长长度

二分

  • 状态计算:此时,计算公差 \(d=a[i]-a[j]\)

    • 如果前面存在 \(a[pos]=a[j]-d\) ,则 \(f[i][j]=f[j][pos]+1\)
    • 否则,\(f[i][j]=2\)
  • 时间复杂度:\(O(n^2logn)\)

双指针

设置等差数列的三项 \(a_L,a_i,a_R\),则有 \(a_R-a_i=a_i-a_L\),枚举中间的 \(i\)\(L\)\(R\) 分别为左右指针,当存在 \(a_R-a_i=a_i-a_L\) 时转移状态 \(f[i][R]=max(f[i][R],f[L][i]+1)\),其中 \(f[L][i]\) 是已知的,因为 \(i\) 从小到大枚举且 \(L<i\),然后移动左右指针任意一个,当 \(a_R-a_i>a_i-a_L\)\(a_i-a_L\) 的公差偏小,\(L--\),反之,\(R++\)

  • 时间复杂度:\(O(n^2)\)

代码

  • 二分
// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5005;
int n,a[N];
int f[N][N];
int main()
{
    read(n);
    for(int i=1;i<=n;i++)read(a[i]);
    sort(a+1,a+1+n);
    int res=n>=2?2:1;
    for(int i=1;i<=n;i++)
    	for(int j=1;j<i;j++)
    	{
    		int d=a[i]-a[j];
    		int pos=upper_bound(a+1,a+1+n,a[j]-d)-a-1;
    		if(pos>=1&&pos<=n&&a[pos]==a[j]-d)
    		{
    			f[i][j]=f[j][pos]+1;
    			res=max(res,f[i][j]);
    		}
    		else
    			f[i][j]=2;
    	}
    printf("%d",res);
    return 0;
}
  • 双指针
// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5005;
int n,a[N];
int f[N][N];
int main()
{
    read(n);
    for(int i=1;i<=n;i++)read(a[i]);
    for(int i=1;i<=n;i++)
    	for(int j=i+1;j<=n;j++)f[i][j]=2;
    sort(a+1,a+1+n);
    int res=n>=2?2:1;
    for(int i=1;i<=n;i++)
    {
    	int L=i-1,R=i+1;
    	while(L>=1&&R<=n)
    	{
    		if(a[R]-a[i]==a[i]-a[L])
    		{
    			f[i][R]=max(f[i][R],f[L][i]+1);
    			res=max(res,f[i][R]);
    			L--;
    		}
    		else if(a[R]-a[i]>a[i]-a[L])L--;
    		else
    			R++;
    	}
    }
    printf("%d",res);
    return 0;
}
posted @ 2022-04-28 16:19  zyy2001  阅读(44)  评论(0编辑  收藏  举报