题目大意:有一些广告牌,为了使跑步者看到固定数量的广告,设计所需租用的最少数量的广告牌。
其实就是区间选点问题:数轴上有n个区间[ai, bi],取尽量少的点,使得每一个区间都至少有一个点。首先对区间进行排序(按b从小到大的顺序,若b相同则按a从大到小的顺序),然后做出贪心选择:选取第一区间最后一个位置的点,然后逐个区间判断,若已经有点则无需处理,没有点的话选择该区间最后位置的点。本题则是变为k个点,道理是相同的,从后往前进行选点就可以了。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define MAXN 1000+10 6 7 struct Interval 8 { 9 int l, r; 10 bool operator < (const Interval& x) const 11 { 12 if (r != x.r) return r < x.r; 13 else return l > x.l; 14 } 15 }; 16 Interval interval[MAXN]; 17 bool payed[20000+100]; 18 19 int main() 20 { 21 #ifdef LOCAL 22 freopen("in", "r", stdin); 23 #endif 24 int T; 25 scanf("%d", &T); 26 while (T--) 27 { 28 int k, n; 29 scanf("%d%d", &k, &n); 30 for (int i = 0; i < n; i++) 31 { 32 int x, y; 33 scanf("%d%d", &x, &y); 34 interval[i].l = min(x, y); 35 interval[i].r = max(x, y); 36 } 37 sort(interval, interval+n); 38 memset(payed, 0, sizeof(payed)); 39 int ans = 0; 40 for (int i = 0; i < n; i++) 41 { 42 int len = interval[i].r - interval[i].l + 1; 43 if (len < k) 44 { 45 for (int j = interval[i].l; j <= interval[i].r; j++) 46 if (payed[10000+j] == false) 47 { 48 payed[10000+j] = true; 49 ans++; 50 } 51 } 52 else 53 { 54 int cnt = 0; 55 for (int j = interval[i].l; j <= interval[i].r; j++) 56 if (payed[10000+j]) cnt++; 57 if (cnt < k) 58 { 59 int remain = k - cnt; 60 int p = interval[i].r; 61 while (p >= interval[i].l && remain > 0) 62 { 63 if (payed[10000+p] == false) 64 { 65 payed[10000+p] = true; 66 ans++; 67 remain --; 68 } 69 p--; 70 } 71 } 72 } 73 } 74 printf("%d ", ans); 75 for (int i = 0; i < 20005; i++) 76 if (payed[i]) printf("%d ", i-10000); 77 if (T) printf(" "); 78 } 79 return 0; 80 }