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