思路:
dp还是挺明显的,思路可以参考最长上升子序列
有点dp的感觉
f
[
i
]
f[i]
f[i]表示考虑前
i
i
i个数,的最大值
当前数有两种删或不删
不删:
f
[
i
]
=
f
[
i
−
1
]
f[i]=f[i-1]
f[i]=f[i−1];
删:
f
[
i
]
=
m
a
x
f
[
j
−
1
]
+
i
−
j
+
1
f[i]=max{f[j-1]+i-j+1}
f[i]=maxf[j−1]+i−j+1
这个转移是
O
(
n
2
)
O(n^2)
O(n2)的显然时间上来不及
考虑优化,第一层循环一定是省不了的
考虑优化掉第二层循环
将j提出了
f
[
i
]
=
m
a
x
f
[
j
−
1
]
−
j
+
i
+
1
f[i]=max{f[j-1]-j}+i+1
f[i]=maxf[j−1]−j+i+1,f[j-1]-j是满足所有
a
[
i
]
=
=
a
[
j
]
a[i]==a[j]
a[i]==a[j]中最大的,这个可以维护一下前缀最大值
#include <bits/stdc++.h>
#define int long long
#define rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define fep(i, a, b) for(int i = (a); i >= (b); --i)
#define _for(i, a, b) for(int i=(a); i<(b); ++i)
#define pii pair<int, int>
#define pdd pair<double,double>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define vi vector<int>
#define inf -0x3f3f3f3f
/*
* 有点dp的感觉
* f[i]表示考虑前i个数,的最大值
* 当前数有两种删或不删
* 不删:f[i]=f[i-1];
* 删:f[i]=max{f[j-1]+i-j+1}
* 这个转移是$O(n^2)$的显然时间上来不及
* 考虑优化,第一层循环一定是省不了的
* 考虑优化掉第二层循环
* 将j提出了$f[i]=max{f[j-1]-j}+i+1$,f[j-1]-j是满足所有a[i]==a[j]中最大的,这个可以维护一下前缀最大值
*/
using namespace std;
const int maxn = 2e5 + 10;
int f[maxn],a[maxn],sum[maxn];
vi p[maxn];
int n;
void solve() {
cin>>n;
rep(i,1,n){
f[i]=0;
sum[i]=inf;
}
rep(i,1,n){
cin>>a[i];
}
//dp
//初始化0、1都无法去转移初始化为0
f[0]=f[1]=0;
rep(i,1,n){
int x=a[i];
f[i]=f[i-1];
//这样转移会tle需要优化
// rep(j,0,p[x].size()-1){
// if(p[x][j]==i) continue;
// f[i]=max(f[i],f[p[x][j]-1]+i-p[x][j]+1);
// }
f[i]=max(sum[x]+i,f[i]);
sum[x]=max(sum[x],f[i-1]-i+1);
}
cout<<f[n]<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freopen("C:\\Users\\24283\\CLionProjects\\untitled2\\1.in", "r", stdin);
int _;
cin >> _;
while (_--)
solve();
return 0;
}