题意:找出整数序列中最长的等差数列。

题解:

  • 一开始直接用了map加上简单哈希,但是Memory limit,可以试着手动写散列表来实现,时间复杂度O(n^2).
#include<algorithm>
#include <iostream>
#include  <cstdlib>
#include  <cstring>
#include  <cassert>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <queue>
#include    <stack>
#include      <set>
#include      
<map>
using namespace std;
#define P(a,b,c) make_pair(a,make_pair(b,c))
#define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,a,n) for (int i=n;i>=a;i--)
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef pair<int,pair<int,int> >pii;
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 1000000007;
const int INF = 0x3f3f3f3f;
ll gcd(ll a, ll b) {
	return b ? gcd(b, a%b) : a;
}
template <class T>
inline bool scan_d(T &ret) {
	char c;
	int sgn;
	if(c=getchar(),c==EOF) return 0; //EOF
	while(c!='?'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='?')?-1:1;
	ret=(c=='?')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } inline void outt(int x) { if(x>9) outt(x/10);
	putchar(x%10+'0');
}
const ll base=1e9;
const int MAXN = 5e3+10;
map<ll,int>mp;
map<ll,int>ccnt;
int a[MAXN];
int b[MAXN];
int main() {
	int n;
	scanf("%d", &n);
	rep(i,1,n) {
		scan_d(b[i]);
	}
	int cnt=1;
	sort(b+1,b+n+1);
	int ans=0;
	int f=0;
	a[1]=b[1];
	rep(i,2,n) {
		if(b[i]==b[i-1]) {
			f++;
			continue;
		} else {
			if(f>ans)ans=f;
			f=0;
		}
		a[++cnt]=b[i];
	}
	n=cnt;
	rep(i,1,n) {
		rep(j,1,i-1) {
			ll d=a[i]-a[j];
			mp[d*base+a[i]]+=mp[d*base+a[j]]+1;
			map<ll,int>::iterator it=mp.find(mp[d*base+a[j]]);
			if(it!=mp.end()) mp.erase(it);
			if(ans<mp[d*base+a[i]])ans=mp[d*base+a[i]];
		}
	}
	printf("%d", ans+1);
	return 0;
}
  • 可以用dp解决,时间复杂度大于O(n^2)。(最坏n^3)
    • 将dp[i][j]看作以a[i],a[j]为结尾的等差数列;(或者开头也行,只要改变i,j的顺序即可)
    • if(a[j]-a[i]==a[i]-a[pre])d[i][j]=max(dp[i][j],dp[pre][i]);
    • 不可以用滚动数组节省空间,因为并没有一种dp顺序能够覆盖原来的状态或将上一轮的最大值当作本轮的状态比较。
//#include<bits/stdc++.h>
#include<algorithm>
#include <iostream>
#include  <fstream>
#include  <cstdlib>
#include  <cstring>
#include  <cassert>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <queue>
#include    <stack>
#include      <set>
#include      
<map>
using namespace std;
#define P(a,b,c) make_pair(a,make_pair(b,c))
#define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,a,n) for (int i=n;i>=a;i--)
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef pair<int,pair<int,int> >pii;
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 1000000007;
const int INF = 0x3f3f3f3f;
ll gcd(ll a, ll b) {
	return b ? gcd(b, a%b) : a;
}
template <class T>
inline bool scan_d(T &ret) {
	char c;
	int sgn;
	if(c=getchar(),c==EOF) return 0; //EOF
	while(c!='?'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='?')?-1:1;
	ret=(c=='?')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } inline void outt(int x) { if(x>9) outt(x/10);
	putchar(x%10+'0');
}
const int MAXN = 1e5+10; 
int n;
int a[MAXN];
int dp[5005][5005];
int main()
{
//	ios::sync_with_stdio(0);
//	ifstream in;
//	ofstream out;
//	in.open("test.txt");
//	out.open("output.txt");
	scan_d(n);
	rep(i,1,n) scan_d(a[i]);
	sort(a+1, a+n+1);
	rep(i,1,n)
		rep(j,1,n)
			dp[i][j] = 2;
	int ans = 2;
	rep(i,1,n-1){
		int pre = i - 1;
		rep(j,i+1,n){
			while (pre>0&&a[j]-a[i]>a[i]-a[pre])pre--;//向前找,因为有中间的于i不连续但满足条件的pre存在(正如i,j可以不连续) 
			if (pre > 0 && a[j]-a[i]==a[i]-a[pre])//就是判断第一个小于等于的符不符合公差d咯 
				dp[i][j] = dp[pre][i] + 1;
			ans = max(ans, dp[i][j]);
		}
	}
	cout << ans << endl;
	return 0;
}

  • 可以用二分解决:时间复杂度大于O(n^2logn)(最坏N^3logn)
    • 枚举以a[i],a[j]开头的所有等差序列
    • 用二分查找下一个元素是否存在
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
//    freopen("in.txt","r",stdin);
    int n;
    int a[5010];
    while(cin>>n)
    {
        for(int i=0;i<n;i++) cin>>a[i];
        sort(a,a+n);
        int d;
        int num;
        int kase=2;
        int ans=2;
        for(int i=0;i<n-ans;i++)
/*这里遍历到n-ans就够了,因为当你的结果是ans是,在从n-ans往后找,即便后面都是等差序列,答案也不会超过ans*/
            for(int j=i+1;j<n-ans;j++)
            {
                d=a[j]-a[i];
                num=a[j];
                kase=2;//更新kase
                while(1)
                {
                    num=num+d;
                    if(binary_search(a,a+n,num))
                        kase++;
                    else
                    {
                        ans=max(ans,kase);
                        break;
                    }
                }
            }
        cout<<ans<<endl;
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注