zoukankan      html  css  js  c++  java
  • 线段树【单点更新,区间更新,区间查询,最值查询】

     写了一下午的线段树,也算是做个总结吧。下面的区间更新写了两种,一种是没有用到懒操作一种是用了的。懒操作主要是在区间更新的时候用到,下面求区间和 and 区间最值都是要用到懒操作的

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int Max = 5e4;
    int N,a[Max];
    typedef struct Tree{
        int L,R;
        int sum;
        int lazy;//需要增加的值
        int Max;
    };
    Tree tree[Max<<2];
    typedef long long ll;
    void push_up(int x)
    {
        tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
        tree[x].Max = max(tree[x<<1].Max,tree[x<<1|1].Max);
    }
    void push_down(int x,int num)
    {
        if(tree[x].lazy){
            tree[x<<1].sum+=tree[x].lazy*(num-(num/2));//每个点需要更新的值*个数
            tree[x<<1|1].sum += tree[x].lazy*(num/2);
    
            tree[x<<1].Max = tree[x].Max+tree[x].lazy;
            tree[x<<1|1].Max = tree[x].Max+tree[x].lazy;
    
            tree[x<<1].lazy += tree[x].lazy;
            tree[x<<1|1].lazy+=tree[x].lazy;
            tree[x].lazy = 0;
        }
    }
    void build(int x,int l,int r)
    {
        tree[x].L = l;
        tree[x].R = r;
        tree[x].sum = 0;
        tree[x].lazy=0;
        if(l==r){
            tree[x].sum=a[l];
            tree[x].Max=a[l];
            return;
        }
        int mid = (l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        push_up(x);
    }
    
    void update(int x,int pos,int val)
    {
        int L = tree[x].L,R=tree[x].R;
        if(L==R)
        {
            tree[x].sum += val;
            tree[x].Max += val;
            return;
        }
        int mid = (L+R)>>1;
        if(pos<=mid)
            update(x<<1,pos,val);
        else
            update(x<<1|1,pos,val);
        push_up(x);
    }
    void update2(int x,int l,int r,int val)//将区间[l,r]的值都加上val【区间更新】
    {
        int L = tree[x].L,R=tree[x].R;
        if(L==R){
            tree[x].sum+=val;
            tree[x].Max+=val;
            return;
        }
        int mid = (L+R)>>1;
        if(l<=mid){
            update2(x<<1,l,r,val);
        }
        if(mid<r){
            update2(x<<1|1,l,r,val);
        }
        push_up(x);
    }
    void update3(int x,int l,int r,int val)
    {
        int L= tree[x].L,R=tree[x].R;
        if(l<=L&&r>=R){
            tree[x].lazy+=val;
            tree[x].Max+=val;
            tree[x].sum += (ll)val*(R-L+1);
            return;
        }
        push_down(x,R-L+1);
        int mid = (L+R)>>1;
        if(l<=mid) update3(x<<1,l,r,val);
        if(mid<r) update3(x<<1|1,l,r,val);
        push_up(x);
    }
    int query(int x,int l,int r)//区间和查询
    {
        int ans = 0;
        int L = tree[x].L, R = tree[x].R;
        if(l<=L&&r>=R)
            return tree[x].sum;
        push_down(x,R-L+1);
        int mid = (l+r)>>1;
        if(l<=mid)
            ans+=query(x<<1,l,r);
        if(mid<r)
            ans+=query(x<<1|1,l,r);
        return ans;
    }
    int searchMax(int x,int l,int r)//区间最值查询
    {
        int L = tree[x].L,R = tree[x].R;
        if(l<=L&&R<=r){
           return tree[x].Max;
        }
        push_down(x,R-L+1);
        int mid = (l+r)>>1;
        int res = -99999;
        if(l<=mid) res=max(res,searchMax(x<<1,l,r));
        if(mid<r) res = max(res,searchMax(x<<1|1,l,r));
        return res;
    }
    int main()
    {
        string str;
        scanf("%d",&N);
        for(int i=1;i<=N;i++)
            scanf("%d",&a[i]);
        build(1,1,N);
        while(1)
        {
            cin>>str;
            if(str[0]=='e')
                break;
            else if(str[0]=='1'){//单点更新
                int pos,val;
                scanf("%d%d",&pos,&val);
                update(1,pos,val);
            }else if(str[0]=='2'){//不用懒标记的区间更新
                int l,r,val;
                scanf("%d%d%d",&l,&r,&val);
                update2(1,l,r,val);
            }else if(str[0]=='3'){//使用懒标记的区间更新
                int l,r,val;
                scanf("%d%d%d",&l,&r,&val);
                update3(1,l,r,val);
            }else if(str[0]=='4'){//区间最值查询
                int l,r;
                scanf("%d%d",&l,&r);
                int ans = searchMax(1,l,r);
                printf("%d
    ",ans);
            }else{//query
                int left,right;
                scanf("%d%d",&left,&right);
                int ans = query(1,left,right);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    

    用了懒标记的和没有用懒标记的不要混在一起使用。

  • 相关阅读:
    Node.js Net 模块+DNS 模块
    php程序报500错误
    Node.js 工具模块-OS模块+path模块
    Node.js GET/POST请求
    Canvas动画+canvas离屏技术
    Python OS 模块
    Python random 模块
    Python time 模块
    Python 迭代器
    Python 生成器
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160180.html
Copyright © 2011-2022 走看看