线段树维护区间最值和区间替换。
1。设setv,maxv,minv分别表示区间替换值和区间最大值和最小值。在找到目标的区间后,如果setv大于当前区间最大值,说明该区间都可以,ans+=L-R+1,同时更新该区间,注意这里maxv和minv都要改成setv。如果setv小于当前区间最小值,那就没有必要更新了,就中断update。其他情况就继续下传。
2。结点信息下传的时候,minv要取该段区间的setv和minv的较大值。
3。结点信息上传的时候,minv维护最小值,maxv维护最大值。
4。原来的线段树中的点表示的是线段,这里是点。所以右端点需要自减一。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <vector> #include <queue> #include <set> #include <map> #include <algorithm> #define ll long long #define INF 2139062143 #define inf -2139062144 #define MOD 20071027 #define MAXN 30 #define LEN 111111<<2 using namespace std; int ans; struct Line_Tree { private: int setv[LEN],maxv[LEN],minv[LEN]; int sz,ql,qr,sv; void PushUp(int o) { maxv[o]=max(maxv[o<<1],maxv[o<<1|1]); minv[o]=min(minv[o<<1],minv[o<<1|1]); } void Pushdown(int o) { if(setv[o]) { setv[o<<1]=setv[o]; setv[o<<1|1]=setv[o]; maxv[o<<1]=max(maxv[o<<1],setv[o<<1]); maxv[o<<1|1]=max(maxv[o<<1|1],setv[o<<1|1]); minv[o<<1]=max(minv[o<<1],setv[o<<1]); minv[o<<1|1]=max(minv[o<<1|1],setv[o<<1|1]); setv[o]=0; } } void myupdate(int o,int L,int R) { if(ql<=L&&R<=qr) { if(sv>=maxv[o]) { ans+=R-L+1; setv[o]=sv; maxv[o]=sv; minv[o]=sv; return ; } if(sv<=minv[o]||L==R) return ; } Pushdown(o); int M=(L+R)>>1; if(ql<=M) myupdate(o<<1,L,M); if(M<qr) myupdate(o<<1|1,M+1,R); PushUp(o); } public: void init(int n) { sz=n; memset(setv,0,sizeof(setv)); memset(maxv,0,sizeof(maxv)); memset(minv,0,sizeof(minv)); } void update(int a,int L,int R) { sv=a; ql=L; qr=R; myupdate(1,1,sz); } }; Line_Tree tree; int main() { int T; scanf("%d",&T); int n; while(scanf("%d",&n)!=EOF&&n) { tree.init(100000); ans=0; int x,y,z; for(int i=0; i<n; ++i) { scanf("%d%d%d",&x,&y,&z); tree.update(z,x,y-1); } printf("%d\n",ans); } return 0; }