题目链接:http://codeforces.com/gym/100231/attachments
题意:
给你n个区间,告诉你每个区间内都有ci个数
然后你需要找一个最小的点集,使得满足这n个区间的条件
Sample input

5

3 7 3

8 10 3

6 8 1

1 3 1

10 11 1

Sample Output

6

解法:

线段树+二分+贪心

首先我们贪心一发,按照右端点排序之后,我们点肯定是优先放在右边

那么我们怎么确认有多少个放右边呢?

二分+线段树就好了,我们二分有多少个点放在右边,然后在用线段树的区间和来check是否大于ci就好了。

需要注意的是这个地方的线段树更新和不是累加,而是覆盖。

//CF GYM 100231B

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct Seg{
    struct node{
        int l, r;
        int sum, lazy;
        node(){}
        int len(){
            return r-l+1;
        }
    }T[maxn*4];
    void pushup(int rt){
        T[rt].sum = T[rt*2].sum + T[rt*2+1].sum;
    }
    void pushdown(int rt){
        if(T[rt].lazy){
            T[rt*2].sum = T[rt].lazy*T[rt*2].len();
            T[rt*2].lazy = T[rt].lazy;
            T[rt*2+1].sum = T[rt].lazy*T[rt*2+1].len() ;
            T[rt*2+1].lazy = T[rt].lazy;
            T[rt].lazy = 0;
        }
    }
    void build(int l, int r, int rt){
        T[rt].l = l, T[rt].r = r, T[rt].sum = 0, T[rt].lazy = 0;
        if(l == r) return ;
        int mid = (l + r) / 2;
        build(l, mid, rt*2);
        build(mid+1, r, rt*2+1);
        pushup(rt);
    }
    void update(int L, int R, int v, int rt)
    {
        if(L <= T[rt].l && T[rt].r <= R){
            T[rt].sum = v*T[rt].len();
            T[rt].lazy = v;
            return;
        }
        pushdown(rt);
        int mid = (T[rt].l + T[rt].r) / 2;
        if(L <= mid) update(L, R, v, rt*2);
        if(mid < R) update(L, R, v, rt*2+1);
        pushup(rt);
    }
    int query(int L, int R, int rt){
        if(L <= T[rt].l && T[rt].r <= R){
            return T[rt].sum;
        }
        pushdown(rt);
        int mid = (T[rt].l + T[rt].r) / 2;
        int res = 0;
        if(L <= mid) res += query(L, R, rt*2);
        if(mid < R) res += query(L, R, rt*2+1);
        return res;
    }
}zxy;

struct Q{
    int l, r, c;
    Q(){}
    Q(int l, int r, int c) : l(l), r(r), c(c){}
}p[51000];

bool cmp(Q a, Q b){
    if(a.r == b.r && a.l == b.l) return a.c < b.c;
    if(a.r == b.r) return a.l > b.l;
    return a.r < b.r;
}

int main()
{
    #ifdef LOCAL
    freopen("1.txt", "r", stdin);
    freopen("1.txt", "w", stdout);
    #endif // LOCAL
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d%d%d", &p[i].l, &p[i].r, &p[i].c);
        p[i].l++, p[i].r++;
    }
    sort(p+1, p+n+1, cmp);
    zxy.build(1, p[n].r+100, 1);
   // puts("233");
    int ans = 0;
    for(int i = 1; i <= n; i++){
        int L = p[i].l - 1, R = p[i].r;
        while(L <= R){
            int mid =(L+R) / 2;
            if(zxy.query(p[i].l, mid, 1) + (p[i].r - mid) >= p[i].c){
                L = mid+1;
            }
            else{
                R = mid-1;
            }
        }
        //cout << "L:" << L << endl;
        ans += (p[i].r - L + 1) - zxy.query(L, p[i].r, 1);
       //cout << "L: p[i].r" << L << " " << p[i].r << endl;
        zxy.update(L, p[i].r, 1, 1);
    }
    printf("%d\n", ans);
    return 0;
}