題目鏈結
現在我們有乙個長度為 n的整數序列 a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。
第一行是乙個整數,表示序列長度 n。
第二行有 n個整數,第 i個整數表示序列的第 i項 ai。
第一行輸出乙個整數,表示最少需要改變多少個數。
第二行輸出乙個整數,表示在改變的數最少的情況下,每個數改變的絕對值之和的最小值。
輸入:4 5 2 3 5
輸出:1 4
第一問題目非常easy
我們發現如果要同時保留a序列中a[i]與a[j]兩個元素,則必須要滿足a[j]-a[i]≥j-i;
移項一下 我們發現 a[j]-j≥a[i]-i;
於是我們發現,我們可以開乙個b陣列其中對於任意元素b[i]=a[i]-i;
顯然 這個b序列一定是不下降的;
於是最少改變多少個數,也就變成了要求b序列的最長不下降子串行,我們可以直接用dp來做複雜度 o(nlogn)
當然 也可以用樹狀陣列來完成這一操作接下來請看第二問
第二問 我們發現一種情況是我們要解決的
每個被保留的b[i]和b[j]之間的均不合法,那麼如何來改變b[i]與b[j]呢?
後面我來給個詳細的證明吧 如果結合我的**思考不出來的話,請看這位大佬的部落格很詳細
就是不斷的縮減所謂的「台階」,最後剩下左邊的高b[i]與右邊的高b[j]
最優解一定是(或者說,一定可以是)左邊的b[i]到b[k]全部變成b[i]並且右邊的b[k+1]到b[j]全部變成b[j]
如果最優解不是這樣,我們可以無償甚至減償來變成這種形態。
然後列舉每個區間的k就好了
code:
#includeusingnamespace
std;
#define int long long
#define re register
const
int maxn=4e4+9,inf=0x3f3f3f3f
;int a[maxn],f[maxn],b[maxn],d[maxn],l[maxn],n,len=1
,sum1[maxn],sum2[maxn];
vector
p[maxn];
signed main()
else
}printf(
"%lld\n
",n-len+1
); p[
0].push_back(0
); b[
0]=-inf;b[n+1]=inf;
memset(f,inf,
sizeof
f); f[
0]=0
;
for(re int i=1;i<=n+1;i++)
}printf(
"%lld
",f[n+1
]);
return0;
}
HAOI2006 數字序列
現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。輸入格式 第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。輸出格式 第一行乙個整數表示最少需要改變多少個數。第二行乙個整數,表示在改變的數最少...
HAOI2006 數字序列
現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。輸入格式 第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。輸出格式 第一行乙個整數表示最少需要改變多少個數。第二行乙個整數,表示在改變的數最少...
HAOI2006 數字序列 dp,二分
現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。求在改變的數最少的情況下,每個數改變的絕對值之和的最小值。n leq 35000 保證資料隨機 第一問很容易,只需要令 b i a i i 然後跑最長不...