BZOJ1049 HAOI2006 数字序列 一般DP

题意:有一个长度为n的整数序列A,将其变为严格单增序列,求:1、最少需要改变多少个数  2、在改变的数最少的情况下,每个数改变的绝对值之和的最小值

题解:

第一问太水,a[i]-=i之后直接跑最长上升子序列即可。

第二问太神,完全没思路,正解

#include <cmath>
#include <cstdio>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=35000+2;
struct HASH{
    int u;
    HASH *next;
    HASH(){}
    HASH(int _u,HASH *_next):u(_u),next(_next){};
}*table[MAXN],mem[MAXN];
int d[MAXN],cnt,a[MAXN],n,f[MAXN];
long long g[MAXN],sum1[MAXN],sum2[MAXN];

int main(){
    cin >> n;
    
    for (int i=1;i<=n;i++) scanf("%d",a+i),a[i]-=i,d[i]=INT_MAX>>1;

    for (int i=n;i>=0;i--){
        table[f[i]]=&(mem[cnt++]=HASH(i,table[f[i]]));
        g[i]=LONG_LONG_MAX>>1;
    }
    g[0]=0,a[0]=INT_MIN>>1;

    for (int i=1;i<=n;i++)
        for (HASH *p=table[f[i]-1];p;p=p->next){
            if (p->u>i) break;
            if (a[p->u]>a[i]) continue;

            for(int k=p->u;k<=i;k++) sum1[k]=abs(a[p->u]-a[k]),sum2[k]=abs(a[i]-a[k]);
            for(int k=p->u+1;k<=i;k++) sum1[k]+=sum1[k-1],sum2[k]+=sum2[k-1];
            for(int k=p->u;k<i;k++) g[i]=min(g[i],g[p->u]+sum1[k]-sum1[p->u]+sum2[i]-sum2[k]);
        }

    cout<<g[n]<<endl;

    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/WDZRMPCBIT/p/6477148.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值