区间覆盖

Given several segments of line (int the X axis) with coordinates [Li, Ri]. You are to choose the minimal
amount of them, such they would completely cover the segment [0, M].

Input
The first line is the number of test cases, followed by a blank line.
Each test case in the input should contains an integer M (1 ≤ M ≤ 5000), followed by pairs “Li Ri”
(|Li|, |Ri| ≤ 50000, i ≤ 100000), each on a separate line. Each test case of input is terminated by pair‘0 0’.
Each test case will be separated by a single line.

Output
For each test case, in the first line of output your programm should print the minimal number of line
segments which can cover segment [0, M]. In the following lines, the coordinates of segments, sorted
by their left end (Li), should be printed in the same format as in the input. Pair ‘0 0’ should not be
printed. If [0, M] can not be covered by given line segments, your programm should print ‘0’ (without
quotes).
Print a blank line between the outputs for two consecutive test cases.

Sample Input
2
1
-1 0
-5 -3
2 5
0 0
1
-1 0
0 1
0 0
Sample Output
0
1
0 1

思路:

把所有区间从小到大排序,每次进行比较,找区间右边尽量大的,直到覆盖整个区间

源代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #include<algorithm>
 5 using namespace std;
 6 #define maxn 100000+5
 7 int M;
 8 struct Seg{
 9     int left;
10     int right;
11     friend bool operator<(const Seg&a, const Seg&b)
12     {
13         if (a.left != b.left)
14             return a.left<b.left;
15         return a.right> b.left;          //现在还不懂为什么要这样/(ㄒoㄒ)/~~
16
17     }
18 }q[maxn];
19 int ai[maxn];
20 int main()
21 {
22     int T;
23     cin >> T;
24     while (T--)
25     {
26         int flag = 0;
27         cin >> M;
28         int Index = 0;
29             while (cin >> q[Index].left >> q[Index].right)
30             {
31
32                 if (q[Index].left==0&&q[Index].right==0)
33                             break;
34                 if (q[Index].right > 0) ++Index;   //把区间右边大于0的才存进去
35             }
36
37         sort(q, q + Index);
38         if (q[0].left > 0)                  //第一个的左边都大于0,表示没有区间可以覆盖目标区间
39         {
40             cout << "0\n";
41             if (T)                        //不是最后一组数据要求输出空行
42                 cout << endl;
43                 continue;
44
45         }
46         int cur = 0;
47         int j = -1;
48         for (int i = 0; i < Index; i++)
49         {
50             if (q[i].left <= cur)     //区间左边小于0的满足初步条件
51             {
52                 if (j == -1)
53                     ai[++j] = i;
54                 else if (q[i].right > q[ai[j]].right)      //找区间右边大的
55                     ai[j] = i;
56             }
57                 else
58                 {
59                     cur = q[ai[j]].right;      //找区间右边尽量大的
60                     ai[++j] = i;
61                 }
62
63                 if (q[ai[j]].right >= M)     //覆盖了整个区间
64                 {
65                     flag = 1;
66                     break;
67                 }
68
69         }
70         if (flag)
71         {
72             cout << j + 1 << endl;
73             for (int i = 0; i <=j; i++)
74
75                 cout << q[ai[i]].left << " " << q[ai[i]].right << endl;
76
77         }
78             else
79
80                 cout << "0\n";
81                 if (T)
82                     cout << endl;
83
84     }
85
86     return 0;
87 }
时间: 2024-08-13 20:43:13

区间覆盖的相关文章

ural Minimal Coverage (区间覆盖)

http://acm.timus.ru/problem.aspx?space=1&num=1303 给出一些区间,选择尽量少的区间能覆盖到[0,m]. 小白p154,典型的区间覆盖问题.一直在想怎么dp.. 首先预处理,先按左端点从小到大排序,若左端点相同右端点从大到小排序,若区间x完全包含y,按照贪心的思想,y是没有意义的,有大区间可以选何必选择小区间.处理完事之后各个区间满足a1 <= a2 <= a3....且b1 <= b2 <= b3... 这样找到第一个覆盖0的

codeforces Gym 100187F F - Doomsday 区间覆盖贪心

F. Doomsday Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/F Description Doomsday comes in t units of time. In anticipation of such a significant event n people prepared m vaults in which, as they think, it will

算法模板——线段树3(区间覆盖值+区间求和)

实现功能——1:区间覆盖值:2:区间求和 相比直接的区间加,这个要注重顺序,因为操作有顺序之分.所以这里面的tag应该有个pushup操作(本程序中的ext) 1 var 2 i,j,k,l,m,n,a1,a2,a3,a4:longint; 3 a,b,d:array[0..100000] of longint; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end;

算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)

实现功能——1:区间加法 2:区间乘法 3:区间覆盖值 4:区间求和 这是个四种常见线段树功能的集合版哦...么么哒(其实只要协调好三种tag的关系并不算太难——前提是想明白了线段树的工作模式) 代码长度几经修改后也大为缩水 还有!!!——通过BZOJ1798反复的尝试,我的出来一个重要结论——尽量减少pushup操作的不必要使用次数,对于程序提速有明显的效果!!! 1 type vet=record 2 a0,a1:longint; 3 end; 4 var 5 i,j,k,l,m,n,a1,

HDU 4509 湫湫系列故事——减肥记II(线段树-区间覆盖 或者 暴力技巧)

http://acm.hdu.edu.cn/showproblem.php?pid=4509 题目大意: 中文意义,应该能懂. 解题思路: 因为题目给的时间是一天24小时,而且还有分钟.为了解题方便,我们将小时换成分钟,那么一天24小时,总共有1440分钟.顾我就可以把一天里的任意HH:MM时间换成分钟.就这样一天的时间就变成[0,1440]区间了. 因为所给的活动最多是5*10^5,如果把活动的时间在线段[0,1440]都修改,那么时间的复杂度最坏是O(5*10^5*1440). (1)方法一

POJ3171 Cleaning Shifts DP,区间覆盖最值

题目大意,N个区间覆盖[T1,T2]及对应的代价S,求从区间M到E的全部覆盖的最小代价是多少. (1 <= N <= 10,000),(0 <= M <= E <= 86,399). 思路是DP,首先将每个区间按照T2从小到大排序,设dp(k)为从m覆盖到k所需最小代价,则有 dp(T2[i]) = min(dp(T2[i]), {dp(j) + Si,  T1[i] - 1<=j <= T2[i]}),对于 {dp(j) + Si,  T1[i] - 1<

区间覆盖(线段树)

区间覆盖(线段树) X轴上方有若干条平行于X轴的线段,求这些线段能够覆盖X轴的总长度? 输入格式 第一行一个数n(n<=100000),表示线段个数: 接下来n行,每行两个整数a[i],b[i](-10^8<=a[i],b[i]<=10^8),代表一个线段的两个端点输出覆盖X轴的长度 输入样例 2 10 12 2 4 输出样例 4 1 /* 2 样例: 3 有两段线 4 1 2 5 2 3 6 */ 7 8 #include <bits/stdc++.h> 9 using n

UVa 10382 Watering Grass (区间覆盖贪心问题+数学)

题意:有一块长为l,宽为w的草地,在其中心线有n个喷水装置,每个装置可喷出以p为中心以r为半径的圆, 选择尽量少的装置,把草地全部润湿. 析:我个去啊,做的真恶心,看起来很简单,实际上有n多个坑啊,首先这个题,应该可以看出来是贪心算法, 具体的说是区间覆盖问题,这个问题总体来说不难,但是在这有了巨多的坑.要注意以下几点: 1.这是一个草坪,不是线段,首先你要先把实验室转化为线段. 2.这个喷水装置喷出是圆,不是矩形,要运用数学知识进行运算. 3.输入的半径的两倍如果小于等于宽度,就得忽略不记.因

贪心--区间覆盖及区间选点问题

区间覆盖: 数轴上有若干区间,选用最少的线段覆盖指定区间. 区间选点:选用最少的区间使每个区间内至少有一个点 样题1: J - Muddy roads Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Farmer John has a problem: the dirt road from his farm to town has suffered in the re

10382 - Watering Grass(贪心 区间覆盖问题)洒水面覆盖

double qiuzhi(int id) { double t1=cc[id].rid*cc[id].rid; double t2=w*w/4; double t3=t1-t2; double t4=sqrt(t3); return t4; } void to_qujian() { for(int i=0; i<t; i++) { double zhi=qiuzhi(i); qq[i].a=cc[i].pos-zhi; qq[i].b=cc[i].pos+zhi; } } 典型的贪心区间覆盖问