4927 线段树练习5
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
查看运行结果
题目描述 Description
有n个数和5种操作
add a b c:把区间[a,b]内的所有数都增加c
set a b c:把区间[a,b]内的所有数都设为c
sum a b:查询区间[a,b]的区间和
max a b:查询区间[a,b]的最大值
min a b:查询区间[a,b]的最小值
输入描述 Input Description
第一行两个整数n,m,第二行n个整数表示这n个数的初始值
接下来m行操作,同题目描述
输出描述 Output Description
对于所有的sum、max、min询问,一行输出一个答案
样例输入 Sample Input
10 6
3 9 2 8 1 7 5 0 4 6
add 4 9 4
set 2 6 2
add 3 8 2
sum 2 10
max 1 7
min 3 6
样例输出 Sample Output
49
11
4
注意
set有可能是0,所以立个flag
错了两次了qwq
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+50;
int n,q,x,y,z;
long long num[N];
struct seg_tree{
int l,r;
long long sum,minn,maxx;//要维护的值
int ax_add,ax_set;//标记
bool flag;
}t[N<<2];
void updata(int m){//回溯数据更改
t[m].sum=t[m<<1].sum+t[m<<1|1].sum;
t[m].maxx=max(t[m<<1].maxx,t[m<<1|1].maxx);
t[m].minn=min(t[m<<1].minn,t[m<<1|1].minn);
return ;
}
void build(int m,int ll,int rr){
t[m].l=ll;t[m].r=rr;
if(ll==rr){
t[m].minn=num[ll];
t[m].maxx=num[ll];
t[m].sum=num[ll];
return ;
}
int mid=ll+rr>>1;
build(m<<1,ll,mid);//递归处理左儿子
build(m<<1|1,mid+1,rr);//右儿子
updata(m);//回溯数据收集
return ;
}
void add(int m,int v){
t[m].sum+=(t[m].r-t[m].l+1)*v;
t[m].maxx+=v;
t[m].minn+=v;
t[m].ax_add+=v;
return ;
}
void set(int m,int v){
t[m].sum=(t[m].r-t[m].l+1)*v;
t[m].maxx=v;
t[m].minn=v;
t[m].ax_add=0;
t[m].ax_set=v;
t[m].flag=1;
return ;
}
void spread(int m){
if(t[m].flag){
set(m<<1,t[m].ax_set);
set(m<<1|1,t[m].ax_set);
t[m].ax_set=0;
t[m].flag=0;
}
if(t[m].ax_add){
add(m<<1,t[m].ax_add);
add(m<<1|1,t[m].ax_add);
t[m].ax_add=0;
}
return ;
}
void change_add(int m,int ll,int rr,int v){
if(t[m].l>=ll&&t[m].r<=rr){
add(m,v);
return ;
}
spread(m);
int mid=t[m].l+t[m].r>>1;
if(mid>=ll) change_add(m<<1,ll,rr,v);
if(mid<rr) change_add(m<<1|1,ll,rr,v);
updata(m);
return ;
}
void change_set(int m,int ll,int rr,int v){
if(t[m].l>=ll&&t[m].r<=rr){
set(m,v);
return ;
}
spread(m);
int mid=t[m].l+t[m].r>>1;
if(mid>=ll) change_set(m<<1,ll,rr,v);
if(mid<rr) change_set(m<<1|1,ll,rr,v);
updata(m);
return ;
}
long long ask_sum(int m,int ll,int rr){
if(t[m].l>=ll&&t[m].r<=rr) return t[m].sum;
spread(m);long long ans=0;
int mid=t[m].l+t[m].r>>1;
if(mid>=ll) ans+=ask_sum(m<<1,ll,rr);
if(mid<rr) ans+=ask_sum(m<<1|1,ll,rr);
return ans;
}
long long ask_minn(int m,int ll,int rr){
if(t[m].l>=ll&&t[m].r<=rr) return t[m].minn;
spread(m);
long long ans=1e10+7;
int mid=t[m].l+t[m].r>>1;
if(mid>=ll) ans=min(ans,ask_minn(m<<1,ll,rr));
if(mid<rr) ans=min(ans,ask_minn(m<<1|1,ll,rr));
return ans;
}
long long ask_maxx(int m,int ll,int rr){
if(t[m].l>=ll&&t[m].r<=rr) return t[m].maxx;
spread(m);long long ans=-1e10+7;
int mid=t[m].l+t[m].r>>1;
if(mid>=ll) ans=max(ans,ask_maxx(m<<1,ll,rr));
if(mid<rr) ans=max(ans,ask_maxx(m<<1|1,ll,rr));
return ans;
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%lld",&num[i]);
build(1,1,n);
while(q--){
string s;
cin>>s;
if(s[1]=='d') scanf("%d%d%d",&x,&y,&z),change_add(1,x,y,z);
if(s[1]=='e') scanf("%d%d%d",&x,&y,&z),change_set(1,x,y,z);
if(s[1]=='u') scanf("%d%d",&x,&y),printf("%lld\n",ask_sum(1,x,y));
if(s[1]=='a') scanf("%d%d",&x,&y),printf("%lld\n",ask_maxx(1,x,y));
if(s[1]=='i') scanf("%d%d",&x,&y),printf("%lld\n",ask_minn(1,x,y));
// init();
}
return 0;
}