「CF1575L」 Longest Array Deconstruction

文章讲述了在解决Luogu竞赛编程中的一个问题时,如何通过观察题意并应用动态规划进行求解,特别强调了空间复杂度的优化,使用树状数组来维护二维偏序,以解决大规模数据范围下的时间效率问题。
摘要由CSDN通过智能技术生成

luogu双倍经验

如果本文出锅,请评论或私信提醒这个蒟蒻修改!

题意

题目给的很清楚了,不多说。

分析

看到题目,因为在dp题单里,所以一眼是个dp,我们先想朴素算法,可以发现,如果设 f i , j f_{i,j} fi,j 表示前 i i i 个数中删掉 j j j 个所能得到的最大结果,若 a i = i a_i=i ai=i,则 f i , j = f i − 1 , j + 1 f_{i,j}=f_{i-1,j}+1 fi,j=fi1,j+1;否则,可以直接从 f i − 1 , j − 1 f_{i-1,j-1} fi1,j1 转移。

可以很快地打出一个 O ( n 2 ) O(n^2) O(n2) 的暴力。

f[1][0]=(a[1]==1);
for(ll i=2;i<=n;++i)f[i][0]=f[i-1][0]+(a[i]==i);
for(ll i=1;i<=n;++i){
    for(ll j=1;j<=i;++j){
        f[i][j]=max(f[i-1][j]+(a[i]==i-j),f[i-1][j-1]);
    }
}

但是由于 1 ≤ n ≤ 2 × 1 0 5 1\le n\le 2\times 10^5 1n2×105,所以它会 TLE+MLE

第一维的 i i i 不可能优化掉。

看第二维 j j j,经过思考后可以发现,因为空间复杂度应是 O ( n ) O(n) O(n) 级别的,就可以设 f i , 0 / 1 f_{i,0/1} fi,0/1 表示第 i i i 个数是否归到 a i a_i ai 的位置上的最大结果。思再想一想,可发现应设 f i f_i fi 表示 i i i 归位的最大结果,因为求 f i , 0 f_{i,0} fi,0 没什么意义。

对此,可得 f i = max ⁡ ( f j ) + 1 ( a j < a i , j − a j ≤ i − a i ) f_i=\max(f_j)+1\quad(a_j<a_i,j-a_j\le i-a_i) fi=max(fj)+1(aj<ai,jajiai),然后可用树状数组维护二维偏序,不会的看这里(能做这题的应该都会吧)。

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll n,a[2000005],c[2000005],m=1e6;
inline ll lowbit(ll x){return x&-x;}
inline void update(ll x,ll val){
    while(x<=m){
        c[x]=max(c[x],val);
        x+=lowbit(x);
    }
}
inline ll ask(ll x){
    ll res=0;
    while(x){
        res=max(res,c[x]);
        x-=lowbit(x);
    }
    return res;
}//树状数组维护二维偏序
vector<ll>cnt[2000005];
signed main(){
    cin>>n;
    for(ll i=1;i<=n;++i){
        cin>>a[i];
        if(i>=a[i]){
            cnt[i-a[i]].push_back(a[i]);//预处理一下可能的i-a[i]
        }
    }
    for(ll i=0;i<=m;++i){
        for(ll j:cnt[i]){
            update(j,ask(j-1)+1);//更新
        }
    }
    cout<<ask(m);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值