等差数列(DP)

题目链接 题目-最长等差数列 (51nod.com)

本题 很容易 得出一个 n2logn 的解法,令 dp[i][j] 表示以 i 结尾,公差为 j 的最长等差数列的长度,由于公差太大,因此我们需要用到 map ,即 用 map<int,int>mp[MAXN] 来进行 dp ,因此复杂度为 n2logn
显然上述做法是会 TLE 的。

我们考虑去优化上面的 dp

对于一个等差数列的连续三项 ai,aj,ak ,他们满足一个式子 2aj=ai+ak ,那么我们可以定义 dp[i][j] 表示以 ai,aj 为最后两项的最长等差数列的长度。
对于一个有序数组 a 来说,我们可以枚举 i,然后从利用双指针进行 dp ,令 L=i1,R=i+1,每次判断 ai2aL+aR 的值

  • ai2==aL+aR 直接更新 dp[i][R]=max(dp[i][R],dp[L][i]+1),然后令 L ,继续更新 dp 数组
  • ai2>aL+aR 由于 ai 过大,那么我们需要令 R++ ,使得 aL+aR 的值增加
  • ai2<aL+aR 由于 ai 过小,那么我们需要令 $ L--,使得 aL+aR 的值减少

注意初始化:f[i][j](i<j) 均为 2

#include <bits/stdc++.h>
using namespace std;

const int N = 5001;
int a[N];
int f[N][N];

signed main() {
  int n; scanf("%d", &n);

  for(int i = 1; i <= n; i ++ ) {
    scanf("%d", a + i);
  }

  if(n <= 2) {
    printf("%d\n", n); return 0;
  } 

  sort(a + 1, a + 1 + n);
  int ans = 2;
  for(int i = 1; i <= n; i ++ ) {
    for(int j = i + 1; j <= n; j ++ ) {
      f[i][j] = 2;
    }
  }
  for(int i = 1; i <= n; i ++ ) {
    int L = i - 1, R = i + 1;
    while(L >= 1 && R <= n) {
      if(a[i] * 2 == a[L] + a[R]) {
        f[i][R] = max(f[i][R], f[L][i] + 1);
        ans = max(ans, f[i][R]);
        L --;
      } else if(a[i] * 2 > a[L] + a[R]) {
        R ++;
      } else {
        L --;
      }
    }
  }
  printf("%d\n", ans);  
  return 0;
}
posted @   ccz9729  阅读(221)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
主题色彩