题目描述
有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。
现用汉语翻译为:
有N个区间,每个区间x,y表示提供的x~y共y-x+1堆优质牧草。你可以选择任意区间但不能有重复的部分。
对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他。
输入输出格式
输入格式:
第一行,N,如题
接下来N行,每行一个数x,y,如题
输出格式:
一个数,最多能吃到的牧草堆数
输入输出样例
输入样例#1:
复制
3 1 3 7 8 3 4
输出样例#1: 复制
5
说明
1<=n<=150000
0<=x<=y<=3000000
3000000的数据范围开始让我RE了一个点。能看出要用DP,就需要找一个状态转移方程。
我们用f[i]表示前i个区间中牛所能吃到的最多的牧草数。
用一个strcut来记录区间,其中 cow[].x记录区间的左端点,cow[].y记录区间的右端点。ans来记录牧草堆数(前缀和)
对于区间进行排序。
接下来我们找一个状态转移方程。
要使f[i]转移的条件就是找到一个j f[j]+y[j]-x[j]+1>f[j]
可以转化成
f[cow[j].y]=max(f[cow[j].y],f[cow[j].x-1]+cow[j].ans);
可以构成状态转移方程的条件是 该j点要在n之前,且该区间的左端点等于i
有以下代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=3000100; int n; int minn,sum; int f[maxn]; struct c{ int x,y; int a,b; int ans; }cow[maxn]; bool cmp(c a,c b){ return a.x==b.x?a.y<b.y:a.x<b.x; } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>cow[i].x>>cow[i].y; cow[i].ans=cow[i].y-cow[i].x+1; minn=max(minn,cow[i].y);//寻找区间最右端 } sort(cow+1,cow+n+1,cmp); int j=1; for(int i=0;i<=minn;i++){ f[i]=max(f[i],f[i-1]); while(j<=n&&cow[j].x==i){ f[cow[j].y]=max(f[cow[j].y],f[cow[j].x-1]+cow[j].ans); j++; } sum=max(f[i],sum); } cout<<sum; }
原文地址:https://www.cnblogs.com/civilization-ga/p/9346721.html
时间: 2024-10-18 06:07:25