闲得无聊刷白书
一开始想得很简单,维护一个区间最小值(修改时忽略下面的高度)和当前区间高度(区间每一点高度都同一才有效),然后就是区间修改,标记什么的。
结果发现下面的高度传不上来。。。。。。。
于是只好规定区间最低高度等于区间高度时才有效,实际查询时可能遍历到所有的叶节点,效率好像很低的样子,然后加一个强剪枝,即查询高度小于当前区间最低高度时直接返回0,然后就A了,感觉和花神游历各国里面的那个剪枝很像。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100000+5;
struct Node{
int l,r,mi,h;
bool mark;
}tr[N*4];
inline void pushup(int o){
tr[o].mi=min(tr[o<<1].mi,tr[o<<1|1].mi);
}
void build(int o,int l,int r){
tr[o].l=l;tr[o].r=r;
tr[o].mi=tr[o].h=0;tr[o].mark=false;
if(l!=r){
int m=l+r>>1;
build(o<<1,l,m);build(o<<1|1,m+1,r);
}
}
void pushdown(int o){
if(tr[o].mark){
tr[o<<1].mark=tr[o<<1|1].mark=true;
tr[o].mark=false;
tr[o<<1].h=tr[o<<1].mi=tr[o<<1|1].h=tr[o<<1|1].mi=tr[o].h;
}
}
int update(int o,int a,int b,int h){
if(h<tr[o].mi)return 0;
int l=tr[o].l,r=tr[o].r;
if((tr[o].h==tr[o].mi&&tr[o].mi)||l==r){
tr[o].h=tr[o].mi=h;
tr[o].mark=1;
return r-l+1;
}
else{
pushdown(o);
int m=l+r>>1,ans;
if(b<=m)ans=update(o<<1,a,b,h);
else if(m<a)ans=update(o<<1|1,a,b,h);
else ans=update(o<<1,a,m,h)+update(o<<1|1,m+1,b,h);
pushup(o);
return ans;
}
}
int main(){
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
build(1,1,100000-1);
int l,r,h,ans=0;
while(n--){
scanf("%d%d%d",&l,&r,&h);
ans+=update(1,l,r-1,h);
}
printf("%d\n",ans);
}
return 0;
}