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


    YbtOJ 大全

    【例题1】求区间和

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

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    【例题2】区间修改

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

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    【例题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 
    #include 
    #
    • 1
    • 2
  • 相关阅读:
    Linux基础知识与实操-篇七:用户身份切换与特殊控制
    js异步任务的简单总结
    Virtualbox Manjaro kde虚拟机系统闪烁
    模型量化:轻量化你的深度学习模型
    阿里云大数据实战记录2:调度实例跑完数据表为空?
    Pytorch常用api详解
    mac电脑版数字图像处理软件:ACDSee Photo Studio 9最新 for Mac
    Java项目硅谷课堂学习笔记-P5讲师管理模块前端
    多线程涉及的其它知识(死锁(等待唤醒机制),内存可见性问题以及定时器)
    Windows11怎样投屏到电视上?
  • 原文地址:https://blog.csdn.net/glorious_dream/article/details/126474469