扶苏的问题
[yLOI2018] 扶苏的问题
题目描述
给定一个长度为
- 给定区间
,将区间内每个数都修改为 。 - 给定区间
,将区间内每个数都加上 。 - 给定区间
,求区间内的最大值。
输入格式
第一行是两个整数,依次表示序列的长度
第二行有
接下来
- 若
,则接下来有三个整数 ,表示将区间 内的每个数都修改为 。 - 若
,则接下来有三个整数 ,表示将区间 内的每个数都加上 。 - 若
,则接下来有两个整数 ,表示查询区间 内的最大值。
输出格式
对于每个
样例 #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
提示
数据规模与约定
- 对于
的数据, , , , 。
思路
这是一道线段树的模板题。需要求出区间内的最大值。可以使用两个懒标记,一个寸增加的,一个存修改的。但是有一个细节,很容易错,就是在打懒标记的时候,如果你打了一个修改的懒标记,前面打的加标记就没用了,要清空!
代码
#include<cstdio>
const long long INF=0x7fffffffffffffff;
#define int long long
template<typename Tp>Tp max(Tp a,Tp b){
return a>b?a:b;
}
template<typename Tp,const int Size>class LineTree{
private:
struct node{
int l,r;
Tp add=0,set=-INF,data=-INF;
};
node t[Size<<3];
int LeftSon(int p){
return p<<1;
}
int RightSon(int p){
return (p<<1)|1;
}
void make_add(int p,Tp data){
t[p].data+=data;
t[p].add+=data;
}
void make_set(int p,Tp data){
t[p].data=data;
t[p].set=data;
t[p].add=0;//清空加标记
}
void push_up(int p){
t[p].data=max(t[LeftSon(p)].data,t[RightSon(p)].data);
}
void push_down(int p){
if(t[p].set!=-INF){
make_set(LeftSon(p),t[p].set);
make_set(RightSon(p),t[p].set);
t[p].set=-INF;
}
if(t[p].add!=0){
make_add(LeftSon(p),t[p].add);
make_add(RightSon(p),t[p].add);
t[p].add=0;
}
}
public:
void build(int p,int l,int r,Tp a[]){
t[p].l=l,t[p].r=r;
if(l==r){t[p].data=a[l];return;}
int mid=(l+r)>>1;
build(LeftSon(p),l,mid,a);
build(RightSon(p),mid+1,r,a);
push_up(p);
}
void update_add(int p,int l,int r,Tp data){
if(l<=t[p].l&&t[p].r<=r){
make_add(p,data);
return;
}
push_down(p);
if(t[LeftSon(p)].r>=l)update_add(LeftSon(p),l,r,data);
if(t[RightSon(p)].l<=r)update_add(RightSon(p),l,r,data);
push_up(p);
}
void update_set(int p,int l,int r,Tp data){
if(l<=t[p].l&&t[p].r<=r){
make_set(p,data);
return;
}
push_down(p);
if(t[LeftSon(p)].r>=l)update_set(LeftSon(p),l,r,data);
if(t[RightSon(p)].l<=r)update_set(RightSon(p),l,r,data);
push_up(p);
}
Tp ask(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r){return t[p].data;}
push_down(p);
Tp ret=-INF;
if(t[LeftSon(p)].r>=l)ret=max(ret,ask(LeftSon(p),l,r));
if(t[RightSon(p)].l<=r)ret=max(ret,ask(RightSon(p),l,r));
return ret;
}
};
LineTree<long long,1000001>tree;
long long a[1000001];
long long n,q;
signed main(){
scanf("%lld%lld",&n,&q);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
tree.build(1,1,n,a);
for(int i=1;i<=q;i++){
long long op,l,r;
scanf("%lld%lld%lld",&op,&l,&r);
if(op==1){
long long x;
scanf("%lld",&x);
tree.update_set(1,l,r,x);
}else if(op==2){
long long x;
scanf("%lld",&x);
tree.update_add(1,l,r,x);
}else{
printf("%lld\n",tree.ask(1,l,r));
}
}
return 0;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/16450980.html,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效