线段树

Posted liusu123456

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树相关的知识,希望对你有一定的参考价值。

技术图片

技术图片

 技术图片

 

 技术图片

 

 技术图片

 

 技术图片

 

 技术图片

技术图片

 技术图片

技术图片

技术图片

技术图片

技术图片

 

 

 技术图片

 

 

 技术图片

技术图片

 技术图片

 技术图片

技术图片

 技术图片

 技术图片

 技术图片技术图片

 技术图片

 技术图片

 技术图片

 技术图片

 技术图片

 技术图片                                   技术图片

 技术图片

 技术图片

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1000010
using namespace std;
int n,m,a[N];
int mx[N*4],mn[N*4];
void pushup(int k)
{
    mx[k]=max(mx[k*2],mx[k*2+1]);
    mn[k]=min(mn[k*2],mn[k*2+1]);
}
void build(int k,int l,int r)
{
    if(l==r)
    {
        mx[k]=mn[k]=a[l];
        return;
    }
    int mid=l+r>>1;
    build(k*2,l,mid);
    build(k*2+1,mid+1,r);
    pushup(k);
}
int ask_max(int k,int l,int r,int z,int y)
{
    if(l==z&&r==y) return mx[k];
    int mid=l+r>>1;
    if(y<=mid) return ask_max(k*2,l,mid,z,y);
    if(z>mid) return ask_max(k*2+1,mid+1,r,z,y);
    return max(ask_max(k*2,l,mid,z,mid),
            ask_max(k*2+1,mid+1,r,mid+1,y));
}
int ask_min(int k,int l,int r,int z,int y)
{
    if(l==z&&r==y) return mn[k];
    int mid=l+r>>1;
    if(y<=mid) return ask_min(k*2,l,mid,z,y);
    if(z>mid) return ask_min(k*2+1,mid+1,r,z,y);
    return min(ask_min(k*2,l,mid,z,mid),
            ask_min(k*2+1,mid+1,r,mid+1,y));
}
void change(int k,int l,int r,int x)
{
    if(l==r)
    {
        mx[k]=mn[k]=a[l];
        return;
    }
    int mid=l+r>>1;
    if(x<=mid) change(k*2,l,mid,x);
    else change(k*2+1,mid+1,r,x);
    pushup(k);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(1,1,n);
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        int ans=ask_max(1,1,n,l,r)-ask_min(1,1,n,l,r);
        cout<<ans<<endl;
    }
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1000010
using namespace std;
int n,m,a[N];
int sum[N*4],len[N*4],ad[N*4];
void pushup(int k)
{
    sum[k]=sum[k*2]+sum[k*2+1];
    len[k]=len[k*2]+len[k*2+1];
}
void A(int k,int x)
{
    sum[k]+=x*len[k];
    ad[k]+=x;
}
void pushdown(int k)
{
    A(k*2,ad[k]);
    A(k*2+1,ad[k]);
    ad[k]=0;
}
void build(int k,int l,int r)
{
    if(l==r)
    {
        sum[k]=a[l];
        len[k]=1;
        return;
    }
    int mid=l+r>>1;
    build(k*2,l,mid);
    build(k*2+1,mid+1,r);
    pushup(k);
}
int ask_sum(int k,int l,int r,int z,int y)
{
    if(l==z&&r==y) return sum[k];
    if(ad[k]) pushdown(k);
    int mid=l+r>>1;
    if(y<=mid) return ask_sum(k*2,l,mid,z,y);
    if(z>mid) return ask_sum(k*2+1,mid+1,r,z,y);
    return ask_sum(k*2,l,mid,z,mid)+
            ask_sum(k*2+1,mid+1,r,mid+1,y);
}
void change(int k,int l,int r,int z,int y,int x)
{
    if(l==z&&r==y)
    {
        A(k,x);
        return;
    }
    if(ad[k]) pushdown(k);
    int mid=l+r>>1;
    if(y<=mid) change(k*2,l,mid,z,y,x);
    else if(z>mid) change(k*2+1,mid+1,r,z,y,x);
    else
    {
        change(k*2,l,mid,z,mid,x);
        change(k*2+1,mid+1,r,mid+1,y,x);
    }
    pushup(k);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(1,1,n);
    cin>>m;
    while(m--)
    {
        int op,a,b,x;
        cin>>op>>a>>b;
        if(op==1)
        {
            cin>>x;
            change(1,1,n,a,b,x);
        }
        else
        {
            int ans=ask_sum(1,1,n,a,b);
            cout<<ans<<endl;
        }
    }
}

以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章

线段树

CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

线段树合并

数据结构——线段树

论线段树:二

线段树