饥饿的奶牛(洛谷 1868)

题目描述

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

现用汉语翻译为:

有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

/*
  最长上升子序列,写了一个n^2的,90分,nlogn的研究了半天没写出来就放弃了。
  还好刚做了 P1280,感觉和这个题很像,做了一便就过了。
  设f[i]为以i作为左端点的最大价值,如果i这个点没有线段要开始,f[i]=f[i+1];
  否则,看看选哪个线段能获得更多的价值。  
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#define M 3000010
#define N 150010
using namespace std;
int f[M],n,m;
bool flag[M];
struct node
{
    int x,y,v;
};node a[N];
int read()
{
    char c=getchar();int num=0,flag=1;
    while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*flag;
}
bool cmp(const node&s1,const node&s2)
{
    return s1.x<s2.x;
}
int erfen(int l,int r,int v)
{
    while(l<=r)
    {
        int m=(l+r)/2;
        if(a[m].x<v)l=m+1;
        else r=m-1;
    }
    return l;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].x=read();
        a[i].y=read();
        a[i].v=a[i].y-a[i].x+1;
        m=max(m,a[i].x);
        flag[a[i].x]=true;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=m;i>=0;i--)
    {
        f[i]=f[i+1];
        if(flag[i])
        {
            int t=erfen(1,n,i);
            for(int j=t;a[j].x==i;j++)
              f[i]=max(f[i],f[a[j].y+1]+a[j].v);
        }
    }
    printf("%d",f[0]);
    return 0;
}
View Code

 

posted @ 2016-08-24 18:10  karles~  阅读(273)  评论(0编辑  收藏  举报