知识点:
线段树(区间覆盖+区间查询)
#include<cstdio>
using namespace std;
typedef long long ll;
struct tree{
int data;
int tag;
}tr[800600];
ll n,q,cas;
void bud_tr(ll r,ll lf,ll rg){
tr[r].tag=0;
if(lf==rg){
tr[r].data=1;(全部赋值为1)
return ;
}
ll lf_r=2*r;
ll rg_r=2*r+1;
ll mid=(lf+rg)/2;
bud_tr(lf_r,lf,mid);
bud_tr(rg_r,mid+1,rg);
tr[r].data=tr[lf_r].data+tr[rg_r].data;
}
void change(ll r,ll lf,ll rg,ll k){
tr[r].data=k*(rg-lf+1);(直接覆盖就好)
tr[r].tag=k;
}
void push_down(ll r,ll lf,ll rg){
if(tr[r].tag==0)return ;(注意,这个一定要加上,要考虑当前tag为0的情况,不然的话会覆盖为0,当然其实一开始令所有tag为1也行,但是这样的话重复执行耗费时间)
ll mid=(lf+rg)/2;
change(2*r,lf,mid,tr[r].tag);
change(2*r+1,mid+1,rg,tr[r].tag);
tr[r].tag=0;
}
void update(ll r,ll srt,ll edi,ll lf,ll rg,ll k){
if(lf<=srt&&edi<=rg){(在区间内则进行覆盖)
change(r,srt,edi,k);
return ;
}
ll lf_r=2*r;
ll rg_r=2*r+1;
ll mid=(srt+edi)/2;
push_down(r,srt,edi);
if(lf<=mid)update(lf_r,srt,mid,lf,rg,k);
if(mid<rg)update(rg_r,mid+1,edi,lf,rg,k);
tr[r].data=tr[lf_r].data+tr[rg_r].data;
}
int main(){
scanf("%lld",&cas);
ll i,j,n,m,x,y,k;
for(i=1;i<=cas;i++){
scanf("%lld",&n);
for(j=1;j<=4*n+30;j++)(注意,这里不能用memset,不然会WA!)
tr[j].data=tr[j].tag=0;
bud_tr(1,1,n);
scanf("%lld",&m);
for(j=1;j<=m;j++){
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k);
}
printf("Case %lld: The total value of the hook is %lld.\n",i,tr[1].data);
}
}
总结:其实和普通的线段树没太大区别,就是改一改而已。