【清北前紧急补课6】饥饿的奶牛

题目描述

有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。

现用汉语翻译为:

有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;
}

猜你喜欢

转载自www.cnblogs.com/civilization-ga/p/9346721.html