P1868 饥饿的奶牛 线性DP
题目简介
https://www.luogu.com.cn/problem/P1868
思路
这是一道区间问题,基本思路有两种,一种是以位置为阶段,一种是以每个区间为阶段。
最容易想到的方法是以区间为阶段。
首先对每个区间进行排序,这里是以结尾升序排列。
然后是状态:
接着想想怎么得到
这样做乍一看时间复杂度是
由于已经对结尾进行了升序排列,且
因此,只需利用二分查找,找到第一个满足条件的 j 。
再次提一下
这样时间复杂度变为
附上代码:
#include<bits/stdc++.h>
using namespace std;
struct hh
{
long long x,y,s;
}a[200005];
long long n,dp[200005];
bool cmp(hh a,hh b) {return a.y<b.y;}
int erf(int p)
{
int l=0,r=p,mid;
while(l+1<r)
{
mid=(l+r)>>1;
if(a[mid].y<a[p].x) l=mid;
else r=mid;
}
return l;
}
int main()
{
cin>>n;
for(int i=1; i<=n;i++)
{
scanf("%lld%lld",&a[i].x,&a[i].y);
a[i].s=a[i].y-a[i].x+1;
}
sort(a+1,a+1+n,cmp);
for(int i=1; i<=n;i++)
{
dp[i]=max(dp[i-1],dp[erf(i)]+a[i].s);
}
cout<<dp[n];
return 0;
}
总结
区间问题可以令区间为阶段,也可以令位置为阶段,哪个好做用哪个。
对于一些 DP 问题,可以考虑二分优化。