YbtOJ「数据结构」第4章 线段树

YbtOJ 大全

【例题1】求区间和

线段树单点修改,区间查询模板。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define re register
#define int long long
#define drep(a,b,c) for(re int a(b) ; a>=(c) ; --a)
#define rep(a,b,c) 	for(re int a(b) ; a<=(c) ; ++a)
using namespace std;
inline int read(){
   
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
   if(ch == '-') f=-1 ; ch=getchar();}
	while(ch>='0'&&ch<='9'){
   x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int M = 4e5+10;
int a[M];
int n,m;
struct tree{
   
	int val,sum;
}t[M];
#define ls (k<<1)
#define rs (k<<1|1)
inline void pushup(int k) {
    t[k].sum = t[ls].sum + t[rs].sum; }
inline void build(int k,int l,int r){
   
	if(l == r){
   
		t[k].sum = t[k].val = a[l];
		return;
	}
	int mid = (l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(k);
}
inline void modify(int k,int l,int r,int x,int y){
   
	if(l == x && r == x){
   
		t[k].val = y;
		t[k].sum += y;
		return;
	}
	int mid = (l+r)>>1;
	if(x <= mid) modify(ls,l,mid,x,y);
	else modify(rs,mid+1,r,x,y);
	pushup(k);
}
inline int query(int k,int l,int r,int x,int y){
   
	if(x <= l && r <= y) return t[k].sum;
	int mid = (l+r)>>1;
	int res = 0;
	if(x <= mid) res += query(ls,l,mid,x,y);
	if(y > mid)  res += query(rs,mid+1,r,x,y);
	return res;
}
signed main(){
   
	n = read(),m = read();
	build(1,1,n);
	while(m--){
   
		int op = read(),x = read(),y = read();
		if(op == 0) modify(1,1,n,x,y);
		else printf("%lld\n",query(1,1,n,x,y));
	}
	return 0;
}

【例题2】区间修改

线段树区间修改,区间查询模板题,注意每次都要修改 p u s h d o w n pushdown pushdown

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define re register
#define int long long
#define drep(a,b,c) for(re int a(b) ; a>=(c) ; --a)
#define rep(a,b,c) 	for(re int a(b) ; a<=(c) ; ++a)
using namespace std;
inline int read(){
   
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
   if(ch == '-') f=-1 ; ch=getchar();}
	while(ch>='0'&&ch<='9'){
   x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int M = 4e6+10;
int a[M];
int n,m;
struct tree{
   
	int val,sum,lazy;
}t[M];
#define ls (k<<1)
#define rs (k<<1|1)
inline void pushup(int k) {
    t[k].sum = t[ls].sum + t[rs].sum; }
inline void add(int k,int l,int r,int w){
   
	t[k].sum += (r-l+1)*w;
	t[k].lazy += w;
}
inline void pushdown(int k,int l,int r){
   
	int mid = (l+r)>>1;
	add(ls,l,mid,t[k].lazy);
	add(rs,mid+1,r,t[k].lazy);
	t[k].lazy = 0;
}
inline void build(int k,int l,int r){
   
	if(l == r){
   
		t[k].sum = t[k].val = a[l];
		return;
	}
	int mid = (l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(k);
}
inline void modify(int k,int l,int r,int x,int y,int w){
   
	if(x <=l && r <= y){
   
		t[k].sum += (r-l+1)*w;
		t[k].lazy += w;
		return;
	}
	int mid = (l+r)>>1;
	pushdown(k,l,r);
	if(x <= mid) modify(ls,l,mid,x,y,w);
	if(y > mid)  modify(rs,mid+1,r,x,y,w);
	pushup(k);
}
inline int query(int k,int l,int r,int x,int y){
   
	if(x <= l && r <= y) return t[k].sum;
	int mid = (l+r)>>1;
	pushdown(k,l,r);
	int res = 0;
	if(x <= mid) res += query(ls,l,mid,x,y);
	if(y > mid)  res += query(rs,mid+1,r,x,y);
	return res;
}
signed main(){
   
	n = read(),m = read();
	rep(i,1,n) a[i] = read();
	build(1,1,n);
	while(m--){
   
		int op = read(),x = read(),y = read();
		if(op == 1){
   
			int w = read();
			modify(1,1,n,x,y,w);
		}
		else printf("%lld\n",query(1,1,n,x,y));
	}
	return 0;
}

【例题3】公园遛狗

线段树求最大子段和模板。

考虑如何进行 p u s h u p pushup pushup 操作。我们在线段树里维护左端点开始的最大值 l m a x lmax lmax,右端点开始的最大值 r m a x rmax rmax,当前区间的最大值 m x mx mx,当前区间和 s u m sum sum

  • t [ k ] . s u m = t [ l s ] . s u m + t [ r s ] . s u m t[k].sum = t[ls].sum + t[rs].sum t[k].sum=t[ls].sum+t[rs].sum
  • t [ k ] . l m a x = max ⁡ ( t [ l s ] . l m a x , t [ l s ] . s u m + t [ r s ] . l m a x ) t[k].lmax = \max(t[ls].lmax,t[ls].sum+t[rs].lmax) t[k].lmax=max(t[ls].lmax,t[ls].sum+t[rs].lmax)
  • t [ k ] . r m a x = max ⁡ ( t [ r s ] . r m a x , t [ r s ] . s u m + t [ l s ] . r m a x ) t[k].rmax = \max(t[rs].rmax,t[rs].sum+t[ls].rmax) t[k].rmax=max(t[rs].rmax,t[rs].sum+t[ls].rmax)
  • t [ k ] . m x = max ⁡ ( max ⁡ ( t [ l s ] . m x , t [ r s ] . m x ) , t [ l s ] . r m a x + t [ r s ] . l m a x ) t[k].mx = \max(\max(t[ls].mx,t[rs].mx),t[ls].rmax+t[rs].lmax) t[k].mx=max(max(t[ls].mx,t[rs].mx),t[ls].rmax+t[rs].lmax)

注意在询问的时候,要返回一个结构体类型,便于将答案 p u s h u p pushup pushup

#include <cstdio>
#include <iostream>
#
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值