扶苏的问题
题目描述
给定一个长度为
- 给定区间
,将区间内每个数都修改为 。 - 给定区间
,将区间内每个数都加上 。 - 给定区间
,求区间内的最大值。
输入格式
第一行是两个整数,依次表示序列的长度
第二行有
接下来
- 若
,则接下来有三个整数 ,表示将区间 内的每个数都修改为 。 - 若
,则接下来有三个整数 ,表示将区间 内的每个数都加上 。 - 若
,则接下来有两个整数 ,表示查询区间 内的最大值。
输出格式
对于每个
样例 #1
样例输入 #1
6 6
1 1 4 5 1 4
1 1 2 6
2 3 4 2
3 1 4
3 2 3
1 1 6 -1
3 1 6
样例输出 #1
7
6
-1
样例 #2
样例输入 #2
4 4
10 4 -3 -7
1 1 3 0
2 3 4 -4
1 2 4 -9
3 1 4
样例输出 #2
0
数据规模与约定
- 对于
的数据, , , , 。
题解
一道线段树模板题。题目要求我们支持区间修改、区间加和区间求最大值的操作。
用两个lazy标记$ lazyadd
在pushdown的时候,先要pushdown修改标记,再pushdown加标记。
由于要求最大值,所以初始化的时候要初始化成一个极小值。
代码
#include<bits/stdc++.h>
#define INF 0x7fffffffffffffff
#define int long long
using namespace std;
int n,q,op,x,y,z,a[1000010];
struct segtree
{
struct node
{
int lc,rc,data=-INF,lazyadd=-INF,lazych=-INF;
}no[500010<<2];
void build(int l,int r,int num)//建树
{
no[num].lc=l,no[num].rc=r,no[num].lazyadd=-INF,no[num].lazych=-INF;
if(l==r){no[num].data=a[l];return;}
int mid=(l+r)>>1;
build(l,mid,num<<1);
build(mid+1,r,(num<<1)+1);
no[num].data=max(no[num<<1].data,no[(num<<1)+1].data);
}
void addp(int st,int data)//单点加
{
if(no[st].lazyadd==-INF)no[st].lazyadd=0;
no[st].lazyadd+=data;
no[st].data+=data;
}
void changep(int st,int data)//单点修改
{
no[st].lazyadd=-INF;
no[st].lazych=data;
no[st].data=data;
}
void pushdown(int st)
{
if(no[st].lazych!=-INF){
changep(st<<1,no[st].lazych);
changep((st<<1)+1,no[st].lazych);
no[st].lazych=-INF;
}
if(no[st].lazyadd!=-INF){
addp(st<<1,no[st].lazyadd);
addp((st<<1)+1,no[st].lazyadd);
no[st].lazyadd=-INF;
}
}
int getdata(int l,int r,int st)//获取区间最大值
{
int nl=no[st].lc,nr=no[st].rc;
if(nl>r||nr<l)return -INF;
if(l<=nl&&r>=nr)return no[st].data;
pushdown(st);
return max(getdata(l,r,st<<1),getdata(l,r,(st<<1)+1));
}
void add(int l,int r,int st,int data)//区间加
{
int nl=no[st].lc,nr=no[st].rc;
if(nl>r||nr<l)return;
if(l<=nl&&r>=nr){addp(st,data);return;}
pushdown(st);
add(l,r,st<<1,data);
add(l,r,(st<<1)+1,data);
no[st].data=max(no[st<<1].data,no[(st<<1)+1].data);
}
void change(int l,int r,int st,int data)//区间修改
{
int nl=no[st].lc,nr=no[st].rc;
if(nl>r||nr<l)return;
if(l<=nl&&r>=nr){changep(st,data);return;}
pushdown(st);
change(l,r,st<<1,data);
change(l,r,(st<<1)+1,data);
no[st].data=max(no[st<<1].data,no[(st<<1)+1].data);
}
}segt;
signed main()
{
scanf("%lld%lld",&n,&q);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
segt.build(1,n,1);
for(int i=1;i<=q;i++)
{
scanf("%lld",&op);
if(op==1)
{
scanf("%lld%lld%lld",&x,&y,&z);
segt.change(x,y,1,z);
}
else if(op==2)
{
scanf("%lld%lld%lld",&x,&y,&z);
segt.add(x,y,1,z);
}
else if(op==3)
{
scanf("%lld%lld",&x,&y);
printf("%lld\n",segt.getdata(x,y,1));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】