题意:
中文
思路:
线段树裸题,注意不同标记覆盖的问题
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define ls l,mid,rt*2
#define rs mid+1,r,rt*2+1
#define mi (l+r)/2
const int MAXN=1e5+7;
int n,m;
int add[MAXN*4],change[MAXN*4];
int sum[MAXN*4],st,en,v;
void build(int l,int r,int rt){
sum[rt]=add[rt]=0;
change[rt]=-1;
if(l==r) return ;
int mid=mi;
build(ls);build(rs);
}
void push_up(int rt){
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void push_down1(int l,int r,int rt){
if(add[rt]){
int mid=mi;
add[rt*2]+=add[rt];add[rt*2+1]+=add[rt];
sum[rt*2]+=add[rt]*(mid-l+1);
sum[rt*2+1]+=add[rt]*(r-mid);
add[rt]=0;
}
}
void push_down2(int l,int r,int rt){
if(change[rt]!=-1){
int mid=mi;
add[rt*2]=add[rt*2+1]=0;
change[rt*2]=change[rt*2+1]=change[rt];
sum[rt*2]=change[rt]*(mid-l+1);
sum[rt*2+1]=change[rt]*(r-mid);
change[rt]=-1;
}
}
void update1(int l,int r,int rt){
if(l>en||r<st) return ;
if(st<=l&&r<=en){
add[rt]+=v;
sum[rt]+=v*(r-l+1);
return ;
}
int mid=mi;
push_down2(l,r,rt);
push_down1(l,r,rt);
update1(ls);update1(rs);
push_up(rt);
}
void update2(int l,int r,int rt){
if(l>en||r<st) return ;
if(st<=l&&r<=en){
add[rt]=0;change[rt]=v;
sum[rt]=change[rt]*(r-l+1);
return ;
}
int mid=mi;
push_down2(l,r,rt);
push_down1(l,r,rt);
update2(ls);update2(rs);
push_up(rt);
}
int query(int l,int r,int rt){
if(l>en||r<st) return 0;
if(st<=l&&r<=en) return sum[rt];
int mid=mi;
push_down2(l,r,rt);
push_down1(l,r,rt);
return query(ls)+query(rs);
}
int main(){
//freopen("data.in","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=-1){
build(1,n,1);
while(m--){int op;
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&st,&en,&v);
update1(1,n,1);
}else if(op==2){
scanf("%d%d%d",&st,&en,&v);
update2(1,n,1);
}else{
scanf("%d%d",&st,&en);
cout<<query(1,n,1)<<endl;
}
}
}
}