题意:
按先后顺序告诉你每个长方形的左边界和右边界和高度, 求总覆盖度? 当前长方形的覆盖度为 左右的长度 使得他自己的高度最大。
思路:
很明显线段树。
我们直接按照输入顺序依次更新。
线段树里结点存的是线段,而不是点。
记录这个区间高度最大值,最小值。
当最大值小于等于h 时, 在递归更新。直到不能更新或者 区间全都比h小为止。
这样会TLE,要加个剪枝。
当前更新为h 时, 如果h 比最小值都小, 直接剪枝了。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int T;
const int maxn = 100000 + 5;
struct node{
int l,r;
int setv;
int Min, Max;
}nod[maxn<<2];
void build(int l,int r,int o){
nod[o].l = l;
nod[o].r = r;
nod[o].setv = 0;
nod[o].Min = 0;
nod[o].Max = 0;
if (l == r) {
return;
}
int m = l + r >> 1;
build(l, m, o << 1);
build(m+1, r, o << 1 | 1);
}
void pushdown(int o){
if (nod[o].setv){
nod[o<<1].setv = nod[o<<1|1].setv = nod[o].setv;
nod[o<<1].Min = nod[o<<1].Max = nod[o<<1|1].Min = nod[o<<1|1].Max = nod[o].setv;
nod[o].setv = 0;
}
}
void pushup(int o){
int lson = o << 1;
int rson = o << 1 | 1;
nod[o].Min = min(nod[lson].Min, nod[rson].Min);
nod[o].Max = max(nod[lson].Max, nod[rson].Max);
}
int update(int L,int R,int h,int l,int r,int o){
if (nod[o].Min > h) return 0;
if (L <= l && r <= R){
if (l == r){
if (nod[o].Max <= h){
nod[o].Max = nod[o].Min = h;
return 1;
}
else {
return 0;
}
}
else {
if (nod[o].Max <= h){
nod[o].Max = nod[o].Min = h;
nod[o].setv = h;
return r+1-l;
}
if (nod[o].Min > h) return 0;
}
}
int m = l + r >> 1;
pushdown(o);
int ans = 0;
if (m >= L){
ans += update(L,R,h, l, m,o<<1);
}
if (m < R){
ans += update(L,R,h,m+1,r,o<<1|1);
}
pushup(o);
return ans;
}
int main(){
while(scanf("%d",&T) == 1 && T){
while(T--){
int n;
scanf("%d",&n);
int ans = 0;
build(1,100000-1,1);
for (int i = 0; i < n; ++i){
int l,r,h;
scanf("%d %d %d",&l, &r, &h);
ans += update(l, r-1, h, 1, 100000-1, 1);
}
printf("%d\n", ans);
}
}
return 0;
}