【区间选点问题】uva 10148 - Advertisement

区间选点问题,即数轴上有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 ≤ KN ≤ 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 AiBi 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 }

 
时间: 2024-10-11 07:42:37

【区间选点问题】uva 10148 - Advertisement的相关文章

UVa 10148 - Advertisement

题意: 在一个街道上有很多广告位,现在一家公司需要投放广告,要针对具体情况投放.给定一个K值,假如慢跑者经历K以上个路段,至少要看到K个广告位,经历少于等于K个,则需要让慢跑者看到全部广告位,求投放的最少的广告位. 思路:贪心+排序 对于慢跑者经历的路段区间,按区间右端点升序排序,从区间最右端向左遍历每一个慢跑者的区间,对需要设置的广告位进行标记,最后输出标记的点. 注意:输入数据有负值,我的办法是加上一个数,使其转换成非负数. 代码: 1 #include <iostream> 2 #inc

UVa 1615 Highway (贪心,区间选点问题)

题意:给定一个数 n 个点,和一个d,要求在x轴上选出尽量少的点,使得对于给定的每个点,都有一个选出的点离它的欧几里德距离不超过d. 析:首先这是一个贪心的题目,并且是区间选点问题,什么是区间选点呢,就是说在数轴上有 n 个闭区间,取尽量少的点,使得每个区间都至少有一个点. 一看是不是和这个题很相似,是的,那么区间哪里来呢?自己造呗,既然说是距离不超过d,意思就是在给定的点为圆心,以 d 为半径画圆,在x轴上的区间, 那么区间不就有了么,然后这个怎么贪心呢,是这样的,把所有的区间的右端点从小到大

UVA 1615 Highway 高速公路 (区间选点)

题意:在一条线段上选出尽量少的点,使得和所有给出的n个点距离不超过D. 分别计算出每个点在线段的满足条件的区间,然后就转化成了区间选点的问题了,按照右端点排序,相同时按照左端点排序,按照之前的排序一定保证了包含这个点的区间是连续的.贪心,每次选右边的端点,维护一个当前选择点的位置,每遇到区间就判断一下并更新一下点的位置. #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5; struct seg { doubl

区间选点问题

Advertisement:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21426 经典的区间选点问题,要求每个区间内的点数满足条件k个,具体做法是把右端点从小到大排序,然后每次都检查区间内的点数,如果少了,就尽量从右边开始加点,以便于和其他区间共用一点 #include"iostream"#include"algorithm"#include"cstring"using

UVA10148- Advertisement(区间选点)

题意:一段路上,给出n个慢跑者跑步的区间,给出k,要求让每个慢跑者都能看到k个广告,区间都是整数操作,也就是说一个广告只能放在一个整数上,求最小贴的广告数 思路:关于区间选点的问题.把所有区间按B从小到大排序(B相同时A从大到小排序),则如果出现区间包含的情况,小区间一定排在前面.所以贪心的策略就是,从后往前取k个点.因为只有从后面开始取点,满足的区间才最会最多,这样就能达到使用最少的点的目的.注意如果区间长度小于k的话,区间内所有点都要取到. #include <iostream> #inc

poj1328Radar Installation(贪心—区间选点)

题目链接: 啊哈哈,点我点我 题目: Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 52037   Accepted: 11682 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small isl

HDU 4883 TIANKENG’s restaurant(区间选点)

HDU 4883 TIANKENG's restaurant 题目链接 题意:给定一些时间作为区间,和一个人数,问要安排多少人去看管(一个人只能看管一个人) 思路:普通的区间选点问题,一个区间拆成一个进入点一个出去点,然后排序循环求答案即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 20005; struct Man {

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

区间覆盖: 数轴上有若干区间,选用最少的线段覆盖指定区间. 区间选点:选用最少的区间使每个区间内至少有一个点 样题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

UVa1615 Highway (贪心,区间选点)

链接:http://bak.vjudge.net/problem/UVA-1615 分析:以村庄为圆心,D为半径作圆,可选区间就是高速公路在圆内的部分(包括两个交点),按区间右端点从小到大,如若右端点相同再按左端点从大到小排好序,接下来就是很纯粹的区间选点问题. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 using namespace std; 5 6 const int maxn =