【CodeForces - 255C】Almost Arithmetical Progression (dp,離散化)
題幹:
Gena loves sequences of numbers. Recently, he has discovered a new type of sequences which he called an almost arithmetical progression. A sequence is an almost arithmetical progression, if its elements can be represented as:
- a1 = p, where p is some integer;
- ai = ai - 1 + ( - 1)i
Right now Gena has a piece of paper with sequence b, consisting of n integers. Help Gena, find there the longest subsequence of integers that is an almost arithmetical progression.
Sequence s1, s2, ..., sk is a subsequence of sequence b
Input
The first line contains integer n
Output
Print a single integer — the length of the required longest subsequence.
Examples
Input
2
3 5
Output
2
Input
4
10 20 10 30
Output
3
Note
In the first test the sequence actually is the suitable subsequence.
In the second test the following subsequence fits: 10, 20, 10.
題目大意:
給出一個序列,求最長的子序列,滿足隔位的兩個數相等,問這個最長的子序列的長度是多少。
解題報告:
想了好久想到一個dp方程,抱著冒險的心態o(n^2)交一發,TLE41了,,,把離散化的陣列提前預處理了一下,,,又莽了一發,,AC了。。小驚喜。
AC程式碼:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 1e6+5;
int dp[4004][4004];
int a[4004],b[4004];
int cnt[MAX];
int pos[MAX];
int len,n;
int get(int x) {
return lower_bound(b+1,b+len+1,x) - b;
}
int main()
{
cin>>n;
for(int i = 1; i<=n; i++) scanf("%d",a+i),b[i] = a[i],cnt[a[i]]++;
sort(b+1,b+n+1);
len = unique(b+1,b+n+1) - b - 1;
for(int i = 1; i<=n; i++) pos[a[i]] = get(a[i]);
for(int i = 1; i<=n; i++)
for(int j = 1; j<=n; j++)
dp[pos[a[i]]][pos[a[j]]] = 1;
for(int i = 1; i<=n; i++) {
for(int j = 1; j<i; j++) {
if(a[i]!=a[j])
dp[pos[a[i]]][pos[a[j]]] = dp[pos[a[j]]][pos[a[i]]]+1;
}
}
int maxx = -1;
for(int i = 1; i<=n; i++) {
for(int j = 1; j<=n; j++) {
maxx = max(maxx,dp[pos[a[i]]][pos[a[j]]]);
}
}
for(int i = 1; i<=n; i++) {
maxx = max(maxx,cnt[a[i]]);
}
printf("%d\n",maxx);
return 0 ;
}
總結:
思維過程是這樣的,,剛開始想暴力(用vector存權值啊之類的亂搞),,一想肯定不行,,有太多重複操作了。。然後想各種優化後來發現就是要求個序列,,所以跟最長上升子序列聯絡起來了,,後來發現還真可以寫出來個遞推式,,但是是o(n^2)的不知道會不會T,,而且1600W的陣列大小不知道會不會MLE,,交一發,WA,,造樣例,,發現全是同一個數的時候就會爆炸,,我就想,,再多也不可能超過陣列長度啊,,所以就像把元素相等的時候特判一下(並沒想過正確性),改程式碼,,測樣例,,沒啥問題,,再交一發,TLE41,,,失望(但是還是有點小驚喜的因為跑起來了最起碼說明演算法的問題不大)。再想優化,開個陣列預處理一波,去掉了時間複雜度的log,再交,AC。