HAOI2006 數字序列

2022-05-10 22:17:58 字數 1605 閱讀 8548

現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。

輸入格式:

第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。

輸出格式:

第一行乙個整數表示最少需要改變多少個數。

第二行乙個整數,表示在改變的數最少的情況下,每個數改變的絕對值之和的最小值。

輸入樣例#1:複製

4

5 2 3 5

輸出樣例#1:複製

1

4

【資料範圍】

90%的資料n<=6000。

100%的資料n<=35000。

保證所有數列是隨機的。

乙份講解的鏈結

先將陣列每一位a[i]減i

這樣單調上公升就變成了不下降

在給第n+1位加乙個正無窮的值(可以做所有子串的結尾,用於統計第2問的答案)

第一問:求最長不下降串長l

答案就是n-l

第二問:首先令f[i]表示1~i的最長不下降長度,g[i]為將1~i變為不下降的代價

對於一對(i,j)且f[i]=f[j]+1

設w(i,j)為將j+1~i變為單調不下降的最小代價

有乙個結論:

找到乙個斷點k

j+1~k全部變成a[j],k+1~i全部變成a[i]

這樣一定可以找到這個最小代價

證明見鏈結

這個複雜度很玄學,最壞o(n^3),但資料是隨機的,所以遠遠達不到

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;

7 typedef long

long

lol;

8struct

node

9edge[100001

];12

int l,n,head[40001],num,min[40001],a[40001

];13 lol s1[40001],s2[40001],g[40001],f[40001

];14

void add(int u,int

v)15

21int find(int

x)22

30returnas;

31}32int

main()

33 40 ++n;

41 a[n]=(1

<<30

);42 memset(min,127,sizeof

(min));

43 min[0]=-1

<<30;l=0;44

for (i=1;i<=n;i++)

4551 cout52for (i=n;i>=0;i--)

5357 a[0]=-1

<<30;g[0]=0;58

for (i=1;i<=n;i++)

5972

}73 cout<74 }

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 然後跑最長不...