题目链接: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 }