14 CodeTON Round 5 (Div. 1 + Div. 2, Rated, Prizes!)C. Tenzing and Balls(dp+前缀最大值优化)

思路:
dp还是挺明显的,思路可以参考最长上升子序列
有点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]\)中最大的,这个可以维护一下前缀最大值

#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;
}
posted @ 2024-02-29 09:27  cxy8  阅读(1)  评论(0编辑  收藏  举报