题意:找出整数序列中最长的等差数列。
题解:
- 一开始直接用了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;
}
