Codeforces 1400 E. Clear the Multiset —— 暴力一眼DP

   日期:2020-08-28     浏览:117    评论:0    
核心提示:This way题意:给你长度为n的数组,你每次有两种操作:l r 选择一个区间,将这个区间的每个位置的值-1i x 选择一个点i,将这个点的值-x问你要将这个数组清零最少要几次操作题解:数据范围5000,暗示的很明显了。首先考虑二维DPdp[i][j]表示到了第i个位置,1操作的高度为j的时候的答案最小值(注意是高度而不是次数,因为中间可能有阻断的位置)那么有三种转移的情况:dp[i-1][k(kj)]但是每次暴力的

This way

题意:

给你长度为n的数组,你每次有两种操作:
l r 选择一个区间,将这个区间的每个位置的值-1
i x 选择一个点i,将这个点的值-x
问你要将这个数组清零最少要几次操作

题解:

数据范围5000,暗示的很明显了。首先考虑二维DP
dp[i][j]表示到了第i个位置,1操作的高度为j的时候的答案最小值(注意是高度而不是次数,因为中间可能有阻断的位置)
那么有三种转移的情况:dp[i-1][k(k<j)],dp[i-1][j],dp[i-1][k(k>j)]
但是每次暴力的转移复杂度是 O ( n 3 ) O(n^3) O(n3),所以需要考虑优化
对于第一种情况,我们需要知到从哪里转移过来,因为我们要加上高度差值,如果去找的话,每次是 O ( n ) O(n) O(n),但是我们从小往大做,每次实时地记录答案+差值的话,就可以 O ( 1 ) O(1) O(1)转移,mi_pre就是干这个的。
第二种情况直接转移
第三种情况我们要注意,只有当a[i]<=n&&a[i-1]>=a[i]的时候才会有效,因为这样的话,就可能可以少掉一次2操作
需要从大到小做一遍,因为如果你从小到大做的话,然后从前面最大的后缀转移过来的话,你不知道那个位置是否比a[i]大。

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5,inf=1e8;
int dp[N][N],a[N],mi_suf[N];
int main()
{
    int n;
    scanf("%d",&n);
    dp[0][0]=0;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            dp[i][j]=inf;
    dp[0][0]=0;
    mi_suf[n+1]=inf;
    for(int i=n;~i;i--)
        mi_suf[i]=min(mi_suf[i+1],dp[0][i]);
    for(int i=1;i<=n;i++){
        int mi_pre=dp[i-1][0];
        for(int j=0;j<=min(n,a[i]);j++){
            mi_pre++;
            dp[i][j]=mi_pre+(j!=a[i]);
            dp[i][j]=min(dp[i][j],dp[i-1][j]+(j!=a[i]));
            mi_pre=min(mi_pre,dp[i-1][j]);
        }
        if(a[i]<=n&&a[i-1]>=a[i]){
            mi_pre=mi_suf[a[i]];
            for(int j=a[i];~j;j--){
                dp[i][j]=min(dp[i][j],mi_pre);
                if(mi_pre>dp[i-1][j])
                    mi_pre=dp[i-1][j]+1;
            }
        }
        mi_suf[n+1]=inf;
        for(int j=n;~j;j--)
            mi_suf[j]=min(mi_suf[j+1],dp[i][j]);
    }
    int ans=inf;
    for(int i=0;i<=n;i++)ans=min(ans,dp[n][i]);
    printf("%d\n",ans);
    return 0;
}

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服