Description
陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 n 个苹果。苹果成熟的时候,陶
陶就会跑去摘苹果。
陶陶的手不能弯 (他仅能把手伸直),当且仅当陶陶达到的高度与苹果的高度相等的时
候,陶陶才能摘到苹果。
好在陶陶有 m 个板凳,每个板凳的高度可以在区间 [li, ri] 之间上下移动 (即可以随时 变为该区间中任何一个值)。当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。
但是搬板凳对陶陶来说是一件费力的事情,所以他只能选择 k 个板凳来使用。
现在已知 n 个苹果到地面的高度,m 个板凳的高度区间,陶陶能选择的板凳数 k,以
及陶陶把手伸直能达到的高度 h,请帮陶陶算一下她最多能够摘到的苹果的数目。假设她碰
到苹果,苹果就会掉下来。
Input
第一行四个正整数 n,m,h,k,表示苹果的数量、板凳的数量、陶陶把手伸直能达到
的高度和陶陶最多选择的板凳数量。
第一行包含 n 个正整数,第 i 个正整数 ai 表示第 i 个苹果到地面的高度,两个相邻的
整数之间用一个空格隔开。
接下来 m 行,每行两个非负整数 li,ri,表示第 i 个板凳的高度区间。
Output
一个数,表示最多摘到的苹果数。
Sample Input
10 5 110 3
100 200 150 140 129 134 167 198 200 111
0 30
20 40
90 100
100 110
50 60
Sample Output
7
Data Constraint
对于 30% 的数据,m≤10,ai, h≤1000,li
<
<
<script type="math/tex" id="MathJax-Element-15"><</script>ri≤1000
对于 100% 的数据,k≤m≤200,n≤1000000,ai, h≤1000000,li < ri≤1000000
解题思路
dp,先将板凳按右端点排序,用f[i][j]表示一共选了i个板凳,最后一个板凳编号为j。所以可以枚举上一个板凳的位置,转移方程为f[i][j]=max{ f[i-1][i-1]~f[i-1][j-1] }。
代码
#include <bits/stdc++.h>
using namespace std;
int n,m,h,k;
int tree[1000005];
int f[205][205];
struct qj{
int l,r;
}d[205];
bool cmp(qj a,qj b){return a.r<b.r;}
int main(){
scanf("%d%d%d%d",&n,&m,&h,&k);
int Max=-1;
for(int i=1;i<=n;++i){
int a;
scanf("%d",&a);a-=h;
if(a<0) continue;
Max=max(Max,a);
tree[a]+=1;
}
for(int j=1;j<=m;++j){
scanf("%d%d",&d[j].l,&d[j].r);
Max=max(Max,d[j].r);
}
for(int i=1;i<=Max;++i) tree[i]+=tree[i-1];
sort(d+1,d+m+1,cmp);
int ans=0;
for(int i=1;i<=k;++i)
for(int j=1;j<=m;++j)
for(int p=i-1;p<j;++p){
f[i][j]=max(f[i][j],f[i-1][p]+tree[d[j].r]-max((d[j].l?tree[d[j].l-1]:0),tree[d[p].r]));
ans=max(ans,f[i][j]);
}
printf("%d",ans);
return 0;
}