【线段树 懒惰标记】JZOJ_1380 最大值(新版)

题目

 

题意:

    在一个长度为n的序列里进行两种操作:(1)1 x y c表示把a[x]到a[y]增加c,(2)2 x y表示询问区间[x~y]的最大值。

思路:

    这题和1379的差不多,就是第一个操作的时候我们可以先做一个标记,等到查找的时候我们再把标记下传下去,可以使时间得到优化。

代码:

 

#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
	int v,d;
}tree[400500];
int c,x,y,n,m,z,a[100500];
void build(int k,int l,int r)
{
	if (l==r) 
	{
		tree[k].v=a[l];
	    return;
	}		
	int mid=(l+r)>>1;
	build(2*k,l,mid);
	build(2*k+1,mid+1,r);	
	tree[k].v=max(tree[2*k].v,tree[2*k+1].v);//建树
}
void inc(int wz,int l,int r,int x,int y,int val)
{
	if (l==x&&r==y) {tree[wz].d+=val;tree[wz].v+=val;return;}
	if (tree[wz].d!=0)
	{
	    tree[wz*2].d+=tree[wz].d;
	    tree[wz*2].v+=tree[wz].d;
	    tree[wz*2+1].d+=tree[wz].d;
		tree[wz*2+1].v+=tree[wz].d;
		tree[wz].d=0;
	}

	int mid=(l+r)>>1;
	if (y<=mid) inc(wz*2,l,mid,x,y,val);
    else if (x>mid) inc(wz*2+1,mid+1,r,x,y,val);
    else {inc(wz*2,l,mid,x,mid,val);inc(wz*2+1,mid+1,r,mid+1,y,val);}
    tree[wz].v=max(tree[wz*2].v,tree[wz*2+1].v);//进行标记
}
long long find(int wz,int l,int r,int x,int y)
{
	if (x==l&&y==r) {return tree[wz].v;}
	if (tree[wz].d!=0)//如果我们查询的这个区间里有修改我们就下传标记
	{
	    tree[wz*2].d+=tree[wz].d;
	    tree[wz*2].v+=tree[wz].d;
	    tree[wz*2+1].d+=tree[wz].d;
		tree[wz*2+1].v+=tree[wz].d;
		tree[wz].d=0;
	}
	int mid=(l+r)>>1;
	
	if (y<=mid) return find(wz*2,l,mid,x,y);
    else if (x>mid) return find(wz*2+1,mid+1,r,x,y);
    else return max(find(wz*2,l,mid,x,mid),find(wz*2+1,mid+1,r,mid+1,y));
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&m);
	
	while (m--)
	{
		scanf("%d",&c);
		if (c==1) {scanf("%d%d%d",&x,&y,&z);inc(1,1,n,x,y,z);}
		else {scanf("%d%d",&x,&y);printf("%lld\n",find(1,1,n,x,y));}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用 Python 实现线段树查找区间内最大值的代码: ```python class SegmentTree: def __init__(self, nums): self.n = len(nums) self.tree = [0] * (self.n * 4) self.build_tree(nums, 0, 0, self.n - 1) def build_tree(self, nums, i, l, r): if l == r: self.tree[i] = nums[l] else: mid = (l + r) // 2 self.build_tree(nums, i * 2 + 1, l, mid) self.build_tree(nums, i * 2 + 2, mid + 1, r) self.tree[i] = max(self.tree[i * 2 + 1], self.tree[i * 2 + 2]) def query(self, i, l, r, ql, qr): if ql <= l and qr >= r: return self.tree[i] elif ql > r or qr < l: return float('-inf') else: mid = (l + r) // 2 left = self.query(i * 2 + 1, l, mid, ql, qr) right = self.query(i * 2 + 2, mid + 1, r, ql, qr) return max(left, right) ``` 其中,SegmentTree 类的构造函数中,build_tree 方法用于构建线段树;query 方法用于查询区间内的最大值体实现如下: 1. build_tree 方法中,i 是当前节点的下标,l 和 r 分别是当前节点所代表的区间的左端点和右端点。如果区间只有一个元素,则将当前节点的值设为该元素的值;否则,递归构建左右子树,并将当前节点的值设为左右子树中的最大值。 2. query 方法中,i、l 和 r 的含义同上,ql 和 qr 分别是查询区间的左端点和右端点。如果当前节点所代表的区间完全包含在查询区间内,则返回当前节点的值;如果当前节点所代表的区间完全不在查询区间内,则返回负无穷;否则,递归查询左右子树,并返回左右子树中的最大值。 使用示例: ```python nums = [1, 3, 2, 7, 9, 11] st = SegmentTree(nums) print(st.query(0, 0, st.n - 1, 1, 4)) # 输出:7 ``` 其中,nums 是待构建线段树的列表,st 是构建的线段树对象,st.query(0, 0, st.n - 1, 1, 4) 表示查询 nums[1:5] 区间内的最大值,结果为 7。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值