闲得无聊刷白书
一开始想得很简单,维护一个区间最小值(修改时忽略下面的高度)和当前区间高度(区间每一点高度都同一才有效),然后就是区间修改,标记什么的。
结果发现下面的高度传不上来。。。。。。。
于是只好规定区间最低高度等于区间高度时才有效,实际查询时可能遍历到所有的叶节点,效率好像很低的样子,然后加一个强剪枝,即查询高度小于当前区间最低高度时直接返回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; }