线段树+扫描线.
终于把扫描线给搞懂了.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 100010;
struct seg{
int p, h, f;
seg(int a = 0, int b = 0, int c = 0):p(a), h(b), f(c){}
bool operator<(const seg & rhs)const{
return p < rhs.p;
}
}ss[maxn + 1000];
int segs[1010 << 2], cover[1010 << 2],N;
void build(int l, int r, int rt){
segs[rt] = cover[rt] =0;
if(l == r)return;
int m = (l + r) >> 1;
build(lson), build(rson);
}
inline void pushUp(int l, int r,int rt){
if(cover[rt] > 0){//被覆盖
segs[rt] = (r - l + 1);
}else if(l == r){//没有被覆盖并且是原线段
segs[rt] = 0;
}else{//即没被覆盖也不是原线段,那么就是左右两个儿子被覆盖的长度的和
segs[rt] = segs[rt << 1] + segs[rt << 1 | 1];
}
}
void update(int v ,int L, int R, int l, int r, int rt){
if(L <= l && r <= R){
cover[rt] += v;
pushUp(l, r, rt);
return ;
}
int m = (l + r) >> 1;
if(L <= m)update(v, L, R, lson);
if(R > m) update(v, L, R, rson);
pushUp(l, r, rt);
}
int main(){
while(~scanf("%d", &N)){
int maxh = 0, i, m = 0, ans = 0;
for(i = 0; i < N; ++ i){
int l, r, v;
scanf("%d%d%d", &l, &r, &v);
maxh = max(maxh, v);
ss[m++] = seg(l, v, 1);
ss[m++] = seg(r, v, -1);
}
sort(ss, ss + m);
build(1, maxh, 1);
for (int i = 0; i < m - 1; ++i){
update(ss[i].f, 1, ss[i].h, 1, maxh, 1);
ans += segs[1] * (ss[i + 1].p - ss[i].p);
}
printf("%d\n", ans);
}
return 0;
}