饥饿的奶牛(洛谷 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; }