十分明显的一道线段树裸题,但是细节操作比较多,卡了1小时,0.0蒟蒻表示很难受。
根本的解决方法就是线段树的区间更新和维护最值。看了其他大神的博客有的还维护的了一个区间最小值来优化时间,但是仔细一想其实不必要。记录maxv[]和col[](懒惰标记)即可。
详细代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;
const int maxn=200010;
int ans1=0;
int maxv[4*maxn],col[4*maxn],n;//col是懒惰标记,表示该子区间待修改的值。maxv是区间的最大值。
void down(int p){
if(col[p]){//此处已经是最大了不用再判断最大最小。
maxv[p*2]=col[p*2]=col[p];
maxv[p*2+1]=col[p*2+1]=col[p];
col[p]=0;
}
}
void change(int p,int l,int r,int x,int y,int v){
if(col[p]>v)return ;//该区间的待修改的值比v大则返回
if(x<=l&&r<=y&&v>=maxv[p]){
ans1+=(r-l+1);
maxv[p]=v;
col[p]=v;//都是最大值。
return ;
}
if(l==r)return ;//直到找到v比改区间的最大值都大或者遇到l==r才返回。
down(p);//未覆盖前col[p]都是0;
int mid=(l+r)/2;
if(x<=mid)change(p*2,l,mid,x,y,v);
if(y>mid)change(p*2+1,mid+1,r,x,y,v);
maxv[p]=max(maxv[p*2],maxv[p*2+1]);
}
int main(){
int t;
while(scanf("%d",&t)&&t!=0){
while(t--){
ans1=0;
memset(col,0,sizeof(col));
memset(maxv,0,sizeof(maxv));
scanf("%d",&n);
for(int i=1;i<=n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
change(1,1,maxn,a,b-1,c);
}
printf("%d\n",ans1);
}
}
return 0;
}
短码很舒服~~~。