Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7116 | Accepted: 2852 |
Description
Input
Output
Sample Input
4 3 6 2 4 0 2 4 7
Sample Output
4
Source
/*
贪心算法:
先对所有区间按照左端点非降序排序,然后依次处理每个区间,total表示需要的总的点数,期间
用curF, curT分别表示在当前最优情况下,上一个区间取的两个最靠右侧的端点,即curF和curT
可以覆盖当前区间且都不能再往右边挪动了,那么对于下一个区间seg[f, t]按照如下情况处理
(1)f > curT
则curF,curT不能覆盖当前区间,对于当前区间需要增加两个点分别为 curF = t -1, curT = t,即尽量往右取
(2)f <= curT && f > curF,由于curF不能再往右边挪动寻找替换点,因此需要增加一个点:
a. 若curT >= t,增加新点 curF = t - 1,将curT挪到t代替原来的curT
b.若curT < t,用curT代替curF, 增加新点 curT = t
(3)f < curT ,由于上一个区间的左端点肯定位于当前区间左端点的非右侧,所以肯定可以通过挪动curF来为当前区间所用而不影响前一个区间,同理如果需要肯定可以通过挪动curT来为当前区间所用而不影响前一个区间
a. t <= curF, 挪动curF为t-1,挪动curT为t
b. curF < t <= curT,curF不用动,挪动curT到t
c. t > curT,curF, curT均不用替换
*/
#include <iostream> #include <algorithm> #define MAX_N 10000 using namespace std; struct seg { int from, to; }segs[MAX_N + 1]; int n; bool compare(const seg &s1, const seg &s2) { if(s1.from < s2.from) return true; else if(s1.from == s2.from) return s1.to <= s2.to; else return false; } int main() { int i; scanf("%d", &n); for(i = 1; i <= n; i++) scanf("%d%d", &segs[i].from, &segs[i].to); sort(&segs[1], &segs[1] + n, compare); //curF, curT保存取到的最后两个点,初始状态下取第一个seg倒数第二和第一个元素 int curF = segs[1].to - 1, curT = segs[1].to, total = 2; for(i = 2; i <= n; i++) { int newF = curF, newT = curT; //当新段和最后两个点完全不相交 if(segs[i].from > curT) { //取新点,同样尽量往后取 total += 2; newT = segs[i].to; newF = newT - 1; } //curF被超越 else if(segs[i].from > curF) { //此时需要取一个新点 total++; //当前段终点小于curT时,只需取新点segs[i].to - 1作为curF,并将curT平移至segs[i].to(没有加新点,只是做替换) if(curT >= segs[i].to) newF = segs[i].to - 1; //否则将curT作为新的curF并取新点segs[i].to(尽量往后取) else newF = curT; newT = segs[i].to; } //当segs[i].from <= curF时,说明curF仍然可用,不用取新点 else { if(segs[i].to <= curF) //判断是否需要将curT平移至segs[i].to { newF = segs[i].to - 1; newT = segs[i].to; } else if(segs[i].to < curT) newT = segs[i].to; } curF = newF; curT = newT; } printf("%d/n", total); return 0; }