BZOJ1049 數字序列 [DP]

1049: [HAOI2006]數字序列

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1732  Solved: 745
[Submit][Status][Discuss]

Description

  現在我們有一個長度爲n的整數序列A。但是它太不好看了,於是我們希望把它變成一個單調嚴格上升的序列。

但是不希望改變過多的數,也不希望改變的幅度太大。

Input

  第一行包含一個數n,接下來n個整數按順序描述每一項的鍵值。n<=35000,保證所有數列是隨機的

Output

  第一行一個整數表示最少需要改變多少個數。 第二行一個整數,表示在改變的數最少的情況下,每個數改變

的絕對值之和的最小值。

Sample Input


4

5 2 3 5

Sample Output


1

4

HINT

Source

思考

第一問就不說了,LIS水題。
第二問用f[i]表示前i個的最少花費,轉移就從滿足條件:從以a[i]結尾的LIS序列長度-1的j轉移過來。
小技巧:鄰接表存每個合法的j,然後枚舉每個轉移。
可以易證:如果從j轉移到i的話,那麼中間一定有一個k[j,i) ,使得j k 的高度都是a[j]k+1>i 的高度都是i ,花費是最優的。

#include<bits/stdc++.h>
#define N 400000
#define INF 1LL<<60
using namespace std;
int a[N],c[N],n,tot,len,dp[N],head[N];
long long f[N],sumf[N],sums[N];
inline void read(int &res){
    static char ch;int flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
struct data{
    int to,nxt;
}E[N*3];
inline void addedge(int u,int v){
    E[++tot].to=v;E[tot].nxt=head[u];head[u]=tot;
}
inline void LIS(){
    a[++n]=0x3f3f3f3f;a[0]=-a[n];
    for(register int i=0;i<=n;i++) c[i]=0x3f3f3f3f;
    len=1,c[1]=a[1],c[0]=-c[0];
    dp[0]=0,dp[1]=1;
    for(register int i=2;i<=n;i++){
        register int x=upper_bound(c,c+1+len,a[i])-c;
        len=max(len,x);
        c[x]=min(c[x],a[i]);
        dp[i]=x;
    }
    printf("%d\n",n-dp[n]);
}
inline void CHG(){
    for(register int i=n;i>=0;i--)addedge(dp[i],i),f[i]=INF;f[0]=0;
    for(register int i=1,tmp;i<=n;i++)
        for(register int v,j=head[dp[i]-1];j;j=E[j].nxt){
            if(v=E[j].to,v>i)break;
            if(a[v]>a[i])continue;
            for(register int k=v;k<=i;k++)sumf[k]=abs(a[k]-a[v]),sums[k]=abs(a[k]-a[i]);
            for(register int k=v+1;k<=i;k++)sumf[k]+=sumf[k-1],sums[k]+=sums[k-1];
            for(register int k=v;k<i;k++)
                f[i]=min(f[i],f[v]+sumf[k]-sumf[v]+sums[i]-sums[k]);
        }
    printf("%d",f[n]);
}
int main(){
    read(n);
    for(register int i=1;i<=n;i++)
        read(a[i]),a[i]-=i;
    LIS(),CHG();
    return 0;
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章