线段树维护区间最值和区间替换。
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;
}