[LUOGU1868] 饥饿的奶牛 - dp二分

题目描述

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

现用汉语翻译为:

有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

 


 

 

题解

我不会,太菜了,抄的题解;

f[i] 表示考虑到第i个区间的最大值;

f[i] = max(f[i-1],f[j]+len(i));

妥妥n^2我不会下面的了;

因为F肯定是单调不降的,所以我们找到第一个可以满足R[j] < L[i]的区间就可以转移;

于是二分...

我菜到想不到二分,大概是完了

 


 

 

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define ll long long
#define clear(a,x) memset(a, x, sizeof a)
int n;
struct date
{
    ll L, R, len;
}da[150010];
ll f[150010];

inline bool cmp(date a, date b)
{
    if (a.R == b.R) return a.L < b.L;
    return a.R < b.R;
}

inline int Find(int x)
{
    int l = 1, r = x;
    int ans = -1;
    while (l <= r)
    {
        int mid = l + r >> 1;
        if (da[mid].R >= da[x].L) r = mid - 1;
        else l = mid + 1, ans = mid;
    }
    return ans;
}

int main()
{
    scanf("%d", &n);
    for (register int i = 1; i <= n; i ++)
    {
        scanf("%lld%lld", &da[i].L,&da[i].R);
        da[i].len = da[i].R - da[i].L + 1;
    }
    sort (da + 1, da + 1 + n, cmp);
    clear(f, 0xcf);
    f[0] = 0;
    f[1] = da[1].len;
    for (register int i = 2; i <= n; i ++)
    {
        ll j = Find(i);
        if (j != -1) f[i] = max(f[i-1], f[j] + da[i].len);
        else f[i] = max(f[i-1], da[i].len);
    }
    cout << f[n] << endl;
    return 0;
}

 

 

 

posted @ 2018-07-04 11:53  zZhBr  阅读(194)  评论(0编辑  收藏  举报