• 【Asia Yokohama Regional Contest 2018】Arithmetic Progressions


    题目大意:给定 N(1<N<=5000) 个不同元素组成的集合,求从中选出若干数字组成的等差数列最长是多少。

    题解:直接暴力有 (O(n^3)) 的算法,即:枚举等差数列的前两个值,再暴力枚举后面的值进行匹配即可,不过这样做直接去世。。
    考虑 (dp[i][j]) 表示以第 i 个数为数列倒数第二位,第 j 个数为等差数列中的最后一位的最长序列的长度,则:(dp[i][j]=max{dp[l][i]+1,a[i]-a[l]=a[j]-a[i]&&0<l<i})。不过这样还是要枚举 l 进行转移,考虑序列是有序的,对于外层枚举的 i 来说,j 的枚举过程中 i 是不变的,且 a[j] 的值是单调递增的,可以利用单调性,令 l 不断减小,即可得到答案,均摊复杂度为 (O(n^2))

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=5010;
    
    int n,a[maxn],dp[maxn][maxn],ans;
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++){
    		int l=i-1;
    		for(int j=i+1;j<=n;j++){
    			dp[i][j]=2;
    			while(l>=1&&a[j]-a[i]>a[i]-a[l])--l;
    			if(l>=1&&a[j]-a[i]==a[i]-a[l])dp[i][j]=max(dp[i][j],dp[l][i]+1);
    			ans=max(ans,dp[i][j]);
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    2016年10月30日表单标签与样式表分类和选择器
    2016年10月29日常用标签与表格
    2016年10月28日网页属性和通用标签
    10月27日体会目标
    字符串学习笔记
    [51nod1789] 跑得比谁都快
    [洛谷9月月赛]签到题
    [LUOGU2730] 魔板
    [SCOI2009]迷路
    [51nod1074] 约瑟夫问题 V2
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10632593.html
Copyright © 2020-2023  润新知