题目描述
有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。
现用汉语翻译为:
有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
分析:线段覆盖的题一般来说都可以用dp做,而且方式就那么几个.一种是长度特别大,线段非常少的,而且线段数量有限制,例如:传送门,这个时候只能用线段作为状态.这道题线段和长度都非常大,只能有一维,如果设线段的话,我不知道是否和前一个线段重叠,不好处理,那么只能设坐标为状态。那么设f[i]表示1~i中能覆盖到的最多的点的个数,先把线段按照右端点排序,如果当前枚举到的这个点正好位于线段内,那么这个线段不能覆盖,那么f[i] = max{f[j]}(j < i),否则f[i] = max{f[当前线段的左端点l - 1] + r - l + 1}.当然,你也可以选择不覆盖,那么答案就是我们之前处理好的最大值.这道题和noip2010引水入城有异曲同工之妙.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; int n,f[3000010],maxx; struct node { int x,y; }a[150010]; bool cmp(node a,node b) { return a.y < b.y; } int main() { scanf("%d",&n); for(int i = 1; i <= n; i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a + 1, a + 1 + n,cmp); for (int i = 1; i <= n; i++) { for (int j = a[i].y - 1; j >= 0; j--) { if (!f[j]) f[j] = maxx; else break; } f[a[i].y] = max(maxx,f[a[i].x - 1] + a[i].y - a[i].x + 1); maxx = max(maxx,f[a[i].y]); } printf("%d ",f[a[n].y]); return 0; }