题目
假设葱一共有 n n n 棵,第 i i i 棵葱的高度为 a [ i ] a[i] a[i]。
Alice
一共要割最多
k
k
k 刀葱,每刀可以在某一高度割去连续一段葱。
以高度 h h h 在区间 [ l , r ] [l, r ] [l,r] 割一刀葱是合法的,当且仅当区间里的葱的高度都不小于 h h h,此时,这个区间中的葱小于等于 h h h 的未被割的部分都会被割掉。
下面的葱被割掉以后,上面的葱不会掉下来。
请问, k k k 刀以后,割掉的葱的总长度的最大值是多少?
数据范围
测试点 | n n n | k k k | a [ i ] a[i] a[i] |
---|---|---|---|
1 − 4 1-4 1−4 | ≤ 5 \le 5 ≤5 | ≤ 5 \le 5 ≤5 | ≤ 1 0 6 \le 10^6 ≤106 |
5 − 8 5-8 5−8 | ≤ 10 \le 10 ≤10 | ≤ 10 \le 10 ≤10 | ≤ 1 0 6 \le 10^6 ≤106 |
9 − 10 9-10 9−10 | ≤ 100 \le 100 ≤100 | ≤ 2 \le 2 ≤2 | ≤ 1 0 6 \le 10^6 ≤106 |
11 − 12 11-12 11−12 | ≤ 100 \le 100 ≤100 | ≤ 100 \le 100 ≤100 | ≤ 100 \le 100 ≤100 |
13 − 20 13-20 13−20 | ≤ 100 \le 100 ≤100 | ≤ 100 \le 100 ≤100 | ≤ 1 0 6 \le 10^6 ≤106 |
对于所有数据, 1 ≤ n , k ≤ 100 , 1 ≤ a i ≤ 1 0 6 1 \le n,k \le 100,1 \le a_i \le 10^6 1≤n,k≤100,1≤ai≤106。
题解
我们考虑到一段连续的区间,切掉最小值之后分为2个区间,这样到最后最多只有4n个区间。所以我们令
f
[
i
]
[
k
]
[
l
]
f[i][k][l]
f[i][k][l] 表示第
i
i
i 个区间上一刀割在
l
l
l 高度,割了
k
k
k 刀之后的最大价值。于是我们就可以转移。令
x
,
y
x,y
x,y 为
i
i
i 的子区间。
若当前这一刀不割区间最小值,则
f
[
i
]
[
k
]
[
l
]
f[i][k][l]
f[i][k][l] 可以由
f
[
x
]
[
k
1
]
[
l
]
,
f
[
y
]
[
k
−
k
1
]
[
l
]
f[x][k1][l],f[y][k-k1][l]
f[x][k1][l],f[y][k−k1][l]转移。
若割了最小值,令区间最小值为o,则由
f
[
x
]
[
k
1
]
[
o
]
,
f
[
y
]
[
k
−
k
1
−
1
]
[
o
]
f[x][k1][o],f[y][k-k1-1][o]
f[x][k1][o],f[y][k−k1−1][o]转移。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,k,a[N],f[N*4][N][N],qu[N][N],tot,ans,hi[N*4];
void solve(int l,int r,int h){
qu[l][r]=++tot;
int p=0;
for(int i=l;i<=r;++i)if(a[p]>a[i])p=i;
hi[h]=a[p];
if(p>l)solve(l,p-1,h+1);
if(p<r)solve(p+1,r,h+1);
int lt=qu[l][p-1],rt=qu[p+1][r];
for(int i=0;i<=k;++i){
for(int j=0;j<=h;++j){
for(int ck=0;ck<=i;++ck)f[qu[l][r]][i][j]=max(f[qu[l][r]][i][j],f[lt][ck][j]+f[rt][i-ck][j]);
for(int ck=0;ck<i;++ck)f[qu[l][r]][i][j]=max(f[qu[l][r]][i][j],f[lt][ck][h]+f[rt][i-ck-1][h]+(r-l+1)*(hi[h]-hi[j]));
}
}
}
int main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
scanf("%d%d",&n,&k);a[0]=1e9;
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
solve(1,n,1);
printf("%d\n",f[qu[1][n]][k][0]);
return 0;
}