线段树【单点更新,区间更新,区间查询,最值查询】

//单点更新,区间更新,区间查询
#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].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);
}
int searchMax(int x,int l,int r)
{
    int L = tree[x].L,R = tree[x].R;
    if(L==R)
        return tree[x].Max;
    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;
}
void update(int x,int pos,int val)
{
    int L = tree[x].L,R=tree[x].R;
    if(L==R)
    {
        tree[x].sum += val;
        return;
    }
    push_down(x,R-L+1);
    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;
        return;
    }
    push_down(x,R-L+1);
    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].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);
    else
        ans+=query(x<<1|1,l,r);
    return ans;
}
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\n",ans);
        }else{//query
            int left,right;
            scanf("%d%d",&left,&right);
            int ans = query(1,left,right);
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qie_wei/article/details/81204378