题目链接
与仅有add操作的线段树不同,多了set操作,而set的优先级高于add,set会将以前的add操作所得的价值覆盖掉,而add只会在以前的set基础上继续,故set优先级较高。
既然set优先级高,那么就要区别对待set和add,引入变量ap和sp分别表示add和set的标记,若该节点有sp那么下传时清空子节点的add即可。
代码如下
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#define MAXN 100010
#define LL long long
using namespace std;
const LL INF=9223372036854775806;
struct Node{
int l,r,ls,rs;
bool sp,ap;
LL minn,maxn,s,d,st;
};
vector<Node> N;
int n,m;
LL a[MAXN];
void build_tree(int v){
N[v].ap=N[v].sp=0;
if(N[v].l==N[v].r){
N[v].s=N[v].minn=N[v].maxn=a[N[v].l];
return;
}
int mid=(N[v].l+N[v].r)>>1;
N.push_back((Node){N[v].l,mid,0,0,INF,-INF});
N[v].ls=N.size()-1;
N.push_back((Node){mid+1,N[v].r,0,0,INF,-INF});
N[v].rs=N.size()-1;
build_tree(N[v].ls);
build_tree(N[v].rs);
N[v].minn=min(N[N[v].ls].minn,N[N[v].rs].minn);
N[v].maxn=max(N[N[v].ls].maxn,N[N[v].rs].maxn);
N[v].s=N[N[v].ls].s+N[N[v].rs].s;
}
void push_down(int v){
if(N[v].sp){
N[v].s=N[v].st*(LL)(N[v].r-N[v].l+1);
N[v].maxn=N[v].minn=N[v].st;
if(N[v].l<N[v].r){
N[N[v].ls].st=N[N[v].rs].st=N[v].st;
N[N[v].ls].sp=N[N[v].rs].sp=1;
N[N[v].ls].ap=N[N[v].rs].ap=0;
N[N[v].ls].d=N[N[v].rs].d=0;
}
N[v].st=N[v].sp=0;
}
if(N[v].ap){
N[v].s+=N[v].d*(LL)(N[v].r-N[v].l+1);
N[v].maxn+=N[v].d,N[v].minn+=N[v].d;
if(N[v].l<N[v].r){
N[N[v].ls].d+=N[v].d,N[N[v].rs].d+=N[v].d;
N[N[v].ls].ap=N[N[v].rs].ap=1;
}
N[v].d=N[v].ap=0;
}
}
void add(int v,int l,int r,int val){
push_down(v);
if(N[v].r<l||N[v].l>r) return;
else if(N[v].l>=l&&N[v].r<=r){
N[v].ap=1;
N[v].d+=val;
push_down(v);
}
else{
add(N[v].ls,l,r,val);
add(N[v].rs,l,r,val);
N[v].s=N[N[v].ls].s+N[N[v].rs].s;
N[v].maxn=max(N[N[v].ls].maxn,N[N[v].rs].maxn);
N[v].minn=min(N[N[v].ls].minn,N[N[v].rs].minn);
}
}
void set(int v,int l,int r,int x){
push_down(v);
if(N[v].l>r||N[v].r<l) return;
else if(N[v].l>=l&&N[v].r<=r){
N[v].st=x;
N[v].ap=N[v].d=0;
N[v].sp=1;
push_down(v);
}
else{
set(N[v].ls,l,r,x);
set(N[v].rs,l,r,x);
N[v].s=N[N[v].ls].s+N[N[v].rs].s;
N[v].maxn=max(N[N[v].ls].maxn,N[N[v].rs].maxn);
N[v].minn=min(N[N[v].ls].minn,N[N[v].rs].minn);
}
}
LL sum(int v,int l,int r){
if(N[v].l>r||N[v].r<l) return 0;
push_down(v);
if(N[v].l>=l&&N[v].r<=r) return N[v].s;
else return sum(N[v].ls,l,r)+sum(N[v].rs,l,r);
}
LL Get_max(int v,int l,int r){
if(N[v].l>r||N[v].r<l) return -INF;
push_down(v);
if(N[v].l>=l&&N[v].r<=r) return N[v].maxn;
else return max(Get_max(N[v].ls,l,r),Get_max(N[v].rs,l,r));
}
LL Get_min(int v,int l,int r){
if(N[v].l>r||N[v].r<l) return INF;
push_down(v);
if(N[v].l>=l&&N[v].r<=r) return N[v].minn;
else return min(Get_min(N[v].ls,l,r),Get_min(N[v].rs,l,r));
}
int main(){
scanf("%d%d",&n,&m);
N.push_back((Node){1,n,0,0,INF,-INF});
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build_tree(0);
while(m--){
char Type[5]; scanf("%s",Type);
if(Type[0]=='a'){
int a,b,x; scanf("%d%d%d",&a,&b,&x);
add(0,a,b,x);
}
if(Type[0]=='s'&&Type[1]=='e'){
int a,b,x; scanf("%d%d%d",&a,&b,&x);
set(0,a,b,x);
}
if(Type[0]=='s'&&Type[1]=='u'){
int a,b; scanf("%d%d",&a,&b);
printf("%lld\n",sum(0,a,b));
}
if(Type[0]=='m'&&Type[1]=='a'){
int a,b; scanf("%d%d",&a,&b);
printf("%lld\n",Get_max(0,a,b));
}
if(Type[0]=='m'&&Type[1]=='i'){
int a,b; scanf("%d%d",&a,&b);
printf("%lld\n",Get_min(0,a,b));
}
}
return 0;
}