随笔- 22  文章- 0  评论- 10  阅读- 1579 

扶苏的问题

题目描述

给定一个长度为 n 的序列 a,要求支持如下三个操作:

  1. 给定区间 [l,r],将区间内每个数都修改为 x
  2. 给定区间 [l,r],将区间内每个数都加上 x
  3. 给定区间 [l,r],求区间内的最大值。

输入格式

第一行是两个整数,依次表示序列的长度 n 和操作的个数 q
第二行有 n 个整数,第 i 个整数表示序列中的第 i 个数 ai
接下来 q 行,每行表示一个操作。每行首先有一个整数 op,表示操作的类型。

  • op=1,则接下来有三个整数 l,r,x,表示将区间 [l,r] 内的每个数都修改为 x
  • op=2,则接下来有三个整数 l,r,x,表示将区间 [l,r] 内的每个数都加上 x
  • op=3,则接下来有两个整数 l,r,表示查询区间 [l,r] 内的最大值。

输出格式

对于每个 op=3 的操作,输出一行一个整数表示答案。

样例 #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

数据规模与约定

  • 对于 100% 的数据,1n,q1061l,rnop{1,2,3}|ai|,|x|109

题解

一道线段树模板题。题目要求我们支持区间修改、区间加和区间求最大值的操作。
用两个lazy标记$ lazyadd lazych $表示加和修改。
在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;
}

 posted on   hu_led  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示