現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。
輸入格式:
第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。
輸出格式:
第一行乙個整數表示最少需要改變多少個數。
第二行乙個整數,表示在改變的數最少的情況下,每個數改變的絕對值之和的最小值。
輸入樣例#1:複製
45 2 3 5
輸出樣例#1:複製
14
【資料範圍】
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 #include6using
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 然後跑最長不...