現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。
輸入格式:
第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。
輸出格式:
第一行乙個整數表示最少需要改變多少個數。
第二行乙個整數,表示在改變的數最少的情況下,每個數改變的絕對值之和的最小值。
輸入樣例#1:
45 2 3 5
輸出樣例#1: 14
思路:一道 題
(1)第一問
假設第i,j(i=j-i
移項發現a[j]-j>=a[i]-i
隨後我們將每個a[i]-=i,然後去求a的最長不下降序列長度即可,用總長度n減去這個長度就是答案
最長不下降序列很顯然要用nlogn的時間複雜度去搞
(2)第二問
設f[i]為前i為為嚴格公升序序列的最小代價
有乙個結論,就是區間(i,j)變為公升序序列的最小代價為在(i,j)之間找乙個k,
將a[i~k] 都變成a[i],將a[k+1~j] 都變成a[j],這之間的最小值就是這個區間內的最優代價
證明然後直接暴力即可
理論實踐複雜度為o(n^3),但是由於第二重迴圈在隨機資料項可能什麼都沒有,所以實際複雜度應遠小於o(n^3)
#include#include#include#include#include#define inf 19999999999;#define int long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define yx(k,x) for(int k=fir[x];k;k=nxt[k])
using namespace std;
int dp[36000],c[36000],a[36000],n,len,f[36000],sum1[36000],sum2[36000],fir[36000],nxt[36000],to[36000],tot;
void ade(int x,int y)
signed main()c[0]=-inf;len=1,c[1]=a[1];dp[1]=1;
rep(i,2,n)
rep(i,0,n)f[0]=0;
rep(i,1,n)
}printf("%lld\n%lld",n-dp[n],f[n]);
return 0;
}
HAOI2006 數字序列
現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。輸入格式 第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。輸出格式 第一行乙個整數表示最少需要改變多少個數。第二行乙個整數,表示在改變的數最少...
HAOI2006 數字序列 題解
題目鏈結 現在我們有乙個長度為 n的整數序列 a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。第一行是乙個整數,表示序列長度 n。第二行有 n個整數,第 i個整數表示序列的第 i項 ai 第一行輸出乙個整數,表示最少需要改變多少個數...
HAOI2006 數字序列 dp,二分
現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。求在改變的數最少的情況下,每個數改變的絕對值之和的最小值。n leq 35000 保證資料隨機 第一問很容易,只需要令 b i a i i 然後跑最長不...