区间选点问题,即数轴上有n个闭区间[l1i, ri],取尽量少的点,使得每个区间内都至少有一个点。
The Department of Recreation has decided that it must be more profitable, and it wants to sell advertising space along a popular jogging path at a local park. They have built a number of billboards (special signs for advertisements) along the path and have decided to sell advertising space on these billboards. Billboards are situated evenly along the jogging path, and they are given consecutive integer numbers corresponding to their order along the path. At most one advertisement can be placed on each billboard.
A particular client wishes to purchase advertising space on these billboards but needs guarantees that every jogger will see it‘s advertisement at least K times while running along the path. However, different joggers run along different parts of the path.
Interviews with joggers revealed that each of them has chosen a section of the path which he/she likes to run along every day. Since advertisers care only about billboards seen by joggers, each jogger‘s personal path can be identified by the sequence of billboards viewed during a run. Taking into account that billboards are numbered consecutively, it is sufficient to record the first and the last billboard numbers seen by each jogger.
Unfortunately, interviews with joggers also showed that some joggers don‘t run far enough to see K billboards. Some of them are in such bad shape that they get to see only one billboard (here, the first and last billboard numbers for their path will be identical). Since out-of-shape joggers won‘t get to see K billboards, the client requires that they see an advertisement on every billboard along their section of the path. Although this is not as good as them seeing Kadvertisements, this is the best that can be done and it‘s enough to satisfy the client.
In order to reduce advertising costs, the client hires you to figure out how to minimize the number of billboards they need to pay for and, at the same time, satisfy stated requirements.
Input
The first line of the input consist of an integer indicating the number of test cases in theinput. Then there‘s a blank line and the test cases separated by a blank line.
The first line of each test case contains two integers K and N (1 ≤ K, N ≤ 1000) separated by a space. K is the minimal number of advertisements that every jogger must see, and N is the total number of joggers.
The following N lines describe the path of each jogger. Each line contains two integers Ai and Bi (both numbers are not greater than 10000 by absolute value). Ai represents the first billboard number seen by jogger number i and Bi gives the last billboard number seen by that jogger. During a run, jogger i will see billboards Ai, Bi and all billboards between them.
Output
On the first line of the output fof each test case, write a single integer M. This number gives the minimal number of advertisements that should be placed on billboards in order to fulfill the client‘s requirements. Then write M lines with one number on each line. These numbers give (in ascending order) the billboard numbers on which the client‘s advertisements should be placed. Print a blank line between test cases.
Sample input
1 5 10 1 10 20 27 0 -3 15 15 8 2 7 30 -1 -10 27 20 2 9 14 21
Sample output for the sample input
19 -5 -4 -3 -2 -1 0 4 5 6 7 8 15 18 19 20 21 25 26 27【题目大意】某条街道上有很多个广告位,一个公司在这条街上投放广告,因为不同地方的人流量是 不同的,所以公司先做了个调查,共调查了N个人,知道了他们每个人每天在街上走的路段。现在要求找到一些广告位,使得广告位数量最少,但是要求调查到的那 些每人至少看到广告K次。如果有人走的路段广告位少于K个,那么要求他在这个路段的所有广告位都要看到。输出要求的广告位的位置。
【分析】假设每个区间是[li, ri], 那么先按照每个区间的ri从小到大排序,若ri相等,则按照li从大到小排序。下图是排好序的四个区间。为了使得广告位数量最少,那么就要让这些广告位尽量的处在越多人重复经过的地方越好。观察下图可以看出,为了让重叠部分越多,那么每个区间选点时,就要让这些点尽可能的往改区间的右边靠。在对每个区间选点时,先查看该区间之前已经被选好几个点了,如果不够的话再补上。
代码(看过题解):
Note: solve函数中的for循环重点注意理解掌握!!!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int maxn = 1010; 8 const int ADD = 10010; 9 struct Seg 10 { 11 int L, R; 12 bool operator < (const Seg &a) const 13 { 14 if(R != a.R) return R < a.R; 15 else return L > a.L; 16 } 17 }seg[maxn]; 18 int vis[2*ADD]; 19 void solve(int n, int k) 20 { 21 memset(vis, 0, sizeof(vis)); 22 int cnt = 0; 23 for(int i = 0; i < n; i++) 24 { 25 if(seg[i].R - seg[i].L + 1 <= k) 26 { 27 for(int j = seg[i].L; j <= seg[i].R; j++) 28 { 29 if(!vis[j]) 30 cnt++, vis[j] = 1; 31 } 32 } 33 else 34 { 35 int num = 0; 36 for(int j = seg[i].L; j <= seg[i].R; j++) 37 { 38 if(vis[j]) 39 num++; 40 } 41 if(num >= k) continue; 42 for(int j = seg[i].R; j >= seg[i].L; j--) 43 { 44 if(!vis[j]) { 45 cnt++; 46 num++; 47 vis[j] = 1; 48 if(num >= k) break; 49 } 50 } 51 } 52 } 53 printf("%d\n", cnt); 54 for(int i = 0; i < 2*ADD; i++) 55 { 56 if(vis[i]) 57 printf("%d\n", i-ADD); 58 } 59 } 60 int main() 61 { 62 int T; 63 scanf("%d", &T); 64 for(int kase = 0; kase < T; kase++) 65 { 66 if(kase) printf("\n"); 67 int k, n; 68 scanf("%d%d", &k, &n); 69 for(int i = 0; i < n; i++) 70 { 71 scanf("%d%d", &seg[i].L, &seg[i].R); 72 seg[i].L += ADD; seg[i].R += ADD; 73 if(seg[i].L > seg[i].R) {int t = seg[i].L; seg[i].L = seg[i].R; seg[i].R = t;} 74 } 75 sort(seg, seg+n); 76 solve(n, k); 77 } 78 return 0; 79 }