[HDOJ6180]Schedule(贪心,二分, STL)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6180

题意:n个线段拆成k个不相交的集合,要求k最小的情况下,所有线段集合中右端点与左端点差的和最小。

贪心,首先给线段排序,往multiset中插,multiset中的数代表某一个集合的右端点编号。

每次把某个线段放入set中时,要找尽可能靠近右端点,并且在右端点右边的(线段端点可交)

由于stl的二分只能找某个区间内大于等于某个值的数,假如没有就会返回end(),而现在希望找到的是上述,所以对集合内的数去相反数,就可以暴力更新了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 // #define lson l, m, rt << 1
 5 // #define rson m + 1, r, rt << 1 | 1
 6 typedef long long LL;
 7 typedef pair<LL, LL> pii;
 8 const LL maxn = 100100;
 9 LL n, k;
10 LL sum[maxn<<2], add[maxn<<2];
11 vector<pii> seg;
12 multiset<LL> vis;
13 multiset<LL>::iterator it;
14 // LL h[maxn], hcnt;
15 
16 // LL id(LL x) {
17 //     return (lower_bound(h, h+hcnt, x) - h) + 1;
18 // }
19 
20 // void pushUP(LL rt) {
21 
22 //     sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
23 // }
24 
25 // void pushDOWN(LL rt, LL m) {
26 //     if(add[rt]) {
27 //         add[rt<<1] += add[rt];
28 //         add[rt<<1|1] += add[rt];
29 //         sum[rt<<1] += add[rt];
30 //         sum[rt<<1|1] += add[rt];
31 //         add[rt] = 0;
32 //     }
33 // }
34 
35 // void update(LL L, LL R, LL c, LL l, LL r, LL rt) {LL m = (l + r) >> 1;
36 //     if(L <= m) update(L, R, c, lson);
37 //     if(R > m) update(L, R, c, rson);
38 //     pushUP(rt);
39 // }
40 
41 // LL query(LL L, LL R, LL l, LL r, LL rt) {LLs = max(ans, query(L, R, rson));
42 //     return ans;
43 // }
44 
45 signed main() {
46     // freopen("in", "r", stdin);
47     LL T, l, r;
48     scanf("%lld", &T);
49     while(T--) {
50         // memset(sum, 0, sizeof(sum));
51         // memset(add, 0, sizeof(add));
52         // hcnt = 0;
53         seg.clear();
54         scanf("%lld", &n);
55         for(LL i = 0; i < n; i++) {
56             scanf("%lld%lld",&l,&r);
57             // h[hcnt++] = l; h[hcnt++] = r;
58             l++; r++;
59             seg.push_back(pii(l, r));
60         }
61         // sort(h, h+hcnt); hcnt = unique(h, h+hcnt) - h;
62         sort(seg.begin(), seg.end());
63         // for(LL i = 0; i < seg.size(); i++) {
64         //     update(id(seg[i].first), id(seg[i].second), 1, 1, hcnt, 1);
65         // }
66         vis.clear();
67         LL ret = 0;
68         for(LL i = 0; i < n; i++) {
69             it = vis.lower_bound(-seg[i].first);
70             if(it != vis.end()) {
71                 vis.insert(-seg[i].second);
72                 ret += seg[i].second + (*it);
73                 vis.erase(it);
74             }
75             else {
76                 vis.insert(-seg[i].second);
77                 ret += seg[i].second - seg[i].first;
78             }
79         }
80         printf("%lld %lld\n", (LL)vis.size(), ret);
81     }
82     return 0;
83 }

 

posted @ 2017-08-24 19:29  Kirai  阅读(327)  评论(0编辑  收藏  举报