线段树

本文详细介绍了线段树的基本概念及应用场景,并提供了多个实例代码,包括单点更新、成段更新等操作,帮助读者深入理解线段树的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

     线段树,也叫区间树,是一棵平衡二叉树。它在每个节点保存一条线段,通常用于解决数列维护问题,基本能够保证每个操作的时间复杂度为O(logn)。

2.线段树的操作一般包括:单点更新、成段更新、区间合并、扫描线等......(这次先写一点吧微笑):


单点更新:

hdu1754点击打开链接

代码如下:

#include<iostream>
#include<cstdio>
#define MID(x,y) ((x+y)>>1)
#define l(t) t<<1
#define r(t) t<<1|1
#define INF 900000
int ans;
struct Node
{
    int l;
    int r;
    int max;
}tree[INF];
void push_up(int t)
{
    tree[t].max=tree[l(t)].max>tree[r(t)].max?tree[l(t)].max:tree[r(t)].max;
}
void build_tree(int l,int r,int t)
{
    tree[t].l=l; tree[t].r=r;
    if(l==r)
    {
        scanf("%d",&tree[t].max);
        return;
    }
    int mid=MID(l,r);
    build_tree(l,mid,l(t));
    build_tree(mid+1,r,r(t));
    push_up(t);
}
void Update_tree(int l,int r,int t,int num)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        tree[t].max=num;
        return;
    }
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) Update_tree(l,r,l(t),num);
    else if(l>mid) Update_tree(l,r,r(t),num);
    else
    {
        Update_tree(l,mid,l(t),num);
        Update_tree(mid+1,r,r(t),num);
    }
    push_up(t);
}
void query_tree(int l,int r,int t)
{
    if(l==tree[t].l && tree[t].r==r)
    {
        ans=ans>tree[t].max?ans:tree[t].max;
        return;
    }
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) query_tree(l,r,l(t));
    else if(l>mid) query_tree(l,r,r(t));
    else
    {
        query_tree(l,mid,l(t));
        query_tree(mid+1,r,r(t));
    }
}
int main()
{
    int m,n,a,b;
    while(~scanf("%d%d",&n,&m))
    {
        build_tree(1,n,1);
        while(m--)
        {
            char c[5];
            scanf("%s%d%d",c,&a,&b);
            if(c[0]=='U')
                Update_tree(a,a,1,b);
            else
            {
                ans=0;
                query_tree(a,b,1);
                printf("%d\n",ans);
            } 
        }
    }
    return 0;
}


hdu1394点击打开链接

代码如下:

#include<iostream>
#include<cstdio>
#define l(t) t<<1
#define r(t) t<<1|1
#define MID(x,y) ((x+y)>>1)
#define INF 100000
int sum;
struct Node
{
    int l,r;
    int sum;
}tree[INF];
void push_up(int t)
{
    tree[t].sum=tree[l(t)].sum+tree[r(t)].sum;
}
void build_tree(int l,int r,int t)
{
    tree[t].l=l; tree[t].r=r; tree[t].sum=0;
    if(l==r) return;
    int mid=MID(l,r);
    build_tree(l,mid,l(t));
    build_tree(mid+1,r,r(t));
}
void Update_tree(int l,int r,int t)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        tree[t].sum=1;
        return;
    }
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) Update_tree(l,r,l(t));
    else if(l>mid) Update_tree(l,r,r(t));
    else
    {
        Update_tree(l,mid,l(t));
        Update_tree(mid+1,r,r(t));
    }
    push_up(t);
}
void query_tree(int l,int r,int t)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        sum+=tree[t].sum; return;
    }
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) query_tree(l,r,l(t));
    else if(l>mid) query_tree(l,r,r(t));
    else
    {
        query_tree(l,mid,l(t));
        query_tree(mid+1,r,r(t));
    }
}
int main()
{
    int n;
    int a[5005];
    while(~scanf("%d",&n))
    {
        build_tree(1,n,1);
        sum=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            a[i]++;
            if(a[i]+1<=n)
               query_tree(a[i]+1,n,1);
            Update_tree(a[i],a[i],1);
        }
        int ans=sum;
        for(int i=0;i<n;i++)
        {
            sum=sum+(n-a[i])-(a[i]-1);
            if(ans>sum) ans=sum;
        }
        printf("%d\n",ans);
    }
    return 0;
}

成段更新:(需要用到延迟标记)

hdu1698点击打开链接

代码如下:

#include<iostream>
#include<cstdio>
#define l(t) t<<1
#define r(t) t<<1|1
#define MID(x,y) ((x+y)>>1)
#define INF 400000
using namespace std;
struct Node
{
    int l;
    int r;
    int flag;
    int sum;
}tree[INF];
void push_up(int t)
{
    tree[t].sum=tree[l(t)].sum+tree[r(t)].sum;
}
void push_down(int t,int len)
{
    if(tree[t].flag)
    {
        tree[l(t)].flag=tree[r(t)].flag=tree[t].flag;
        tree[l(t)].sum=tree[t].flag*(len-(len>>1));
        tree[r(t)].sum=tree[t].flag*(len>>1);
        tree[t].flag=0;
    }
}
void build_tree(int l,int r,int t)
{
    tree[t].l=l; tree[t].r=r;  tree[t].flag=0;
    if(l==r)
    {
        tree[t].sum=1; return;
    }
    int mid=MID(l,r);
    build_tree(l,mid,l(t));
    build_tree(mid+1,r,r(t));
    push_up(t);
}
void Update_tree(int l,int r,int t,int num)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        tree[t].flag=num;
        tree[t].sum=(r-l+1)*num;
        return;
    }
    push_down(t,tree[t].r-tree[t].l+1);
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) Update_tree(l,r,l(t),num);
    else if(l>mid) Update_tree(l,r,r(t),num);
    else
    {
        Update_tree(l,mid,l(t),num);
        Update_tree(mid+1,r,r(t),num);
    }
    push_up(t);
}
int main()
{
    int t,count=1;
    cin>>t;
    while(t--)
    {
        int n,m,a,b,c;
        scanf("%d%d",&n,&m);
        build_tree(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            Update_tree(a,b,1,c);
        }
        printf("Case %d: The total value of the hook is %d.\n",count++,tree[1].sum);
    }
    return 0;
}

POJ3468 点击打开链接

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define l(t) t<<1
#define r(t) t<<1|1
#define MID(x,y) ((x+y)>>1)
#define INF 400000
#define ll long long
ll sum,c;
struct Node
{
    int l;
    int r;
    ll sum;
    ll flag;
}tree[INF];
void push_up(int t)
{
    tree[t].sum=tree[l(t)].sum+tree[r(t)].sum;
}
void push_down(int t,int num)
{
    if(tree[t].flag)
    {
        tree[l(t)].flag+=tree[t].flag;
        tree[r(t)].flag+=tree[t].flag;
        tree[l(t)].sum+=tree[t].flag*(num-(num>>1));
        tree[r(t)].sum+=tree[t].flag*(num>>1);
        tree[t].flag=0;
    }
}
void build_tree(int l,int r,int t)
{
    tree[t].l=l; tree[t].r=r; tree[t].flag=0;
    if(l==r)
    {
        scanf("%lld",&tree[t].sum);
        return;
    }
    int mid=MID(l,r);
    build_tree(l,mid,l(t));
    build_tree(mid+1,r,r(t));
    push_up(t);
}
void Update_tree(int l,int r,int t,int num)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        tree[t].flag+=num;
        tree[t].sum+=num*(r-l+1);
        return ;
    }
    push_down(t,tree[t].r-tree[t].l+1);
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) Update_tree(l,r,l(t),num);
    else if(l>mid) Update_tree(l,r,r(t),num);
    else
    {
        Update_tree(l,mid,l(t),num);
        Update_tree(mid+1,r,r(t),num);
    }
    push_up(t);
}
void query_tree(int l,int r,int t)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        sum+=tree[t].sum;
        return ;
    }
    push_down(t,tree[t].r-tree[t].l+1);
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) query_tree(l,r,l(t));
    else if(l>mid) query_tree(l,r,r(t));
    else
    {
        query_tree(l,mid,l(t));
        query_tree(mid+1,r,r(t));
    }
}
int main()
{
    int n,q,a,b;
    //ll c;
    char str[5];
    while(~scanf("%d%d",&n,&q))
    {
        build_tree(1,n,1);
        while(q--)
        {
            scanf("%s",str);
            if(str[0]=='Q')
            {
                sum=0;
                scanf("%d%d",&a,&b);
                query_tree(a,b,1);
                printf("%lld\n",sum);
            }
            else
            {
                scanf("%d%d%lld",&a,&b,&c);
                Update_tree(a,b,1,c);
            }
        }
    }
    return 0;
}

POJ2528 点击打开链接

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define l(t) (t<<1)
#define r(t) (t<<1|1)
#define MID(x,y) ((x+y)>>1)
#define INF 20010
using namespace std;
int result[INF],visit[INF];
int ncase,cnt,n;
struct Node
{
    int l,r;
    int color;
}tree[INF*4];
struct _node
{
    int id;
    int num;
}Max[INF];
bool cmp(_node a,_node b)
{
    return a.num<b.num;
}
int discretize()
{
    cin>>n;
    for(int i=0;i<n*2;i++)
    {
        scanf("%d",&Max[i].num);
        Max[i].id=i;
    }
    sort(Max,Max+n*2,cmp);
    int j=0;
    for(int i=0;i<n*2;i++)
    {
        if(i==0 || Max[i].num!=Max[i-1].num) result[Max[i].id]=++j;
        else result[Max[i].id]=j;
    }
    return result[Max[n*2-1].id];
}
void push_down(int t)
{
    if(tree[t].color)
    {
        tree[l(t)].color=tree[r(t)].color=tree[t].color;
        tree[t].color=0;
    }
}
void build_tree(int l,int r,int t)
{
    tree[t].l=l; tree[t].r=r; tree[t].color=0;
    if(l==r) return;
    int mid=MID(l,r);
    build_tree(l,mid,l(t));
    build_tree(mid+1,r,r(t));
}
void Update_tree(int l,int r,int t,int color)
{
    if(tree[t].l==l && tree[t].r==r)
    {
        tree[t].color=color;
        return;
    }
    push_down(t);
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) Update_tree(l,r,l(t),color);
    else if(l>mid) Update_tree(l,r,r(t),color);
    else
    {
        Update_tree(l,mid,l(t),color);
        Update_tree(mid+1,r,r(t),color);
    }
}
void query_tree(int l,int r,int t)
{
    if(tree[t].color)
    {
        if(!visit[tree[t].color]) {cnt++;visit[tree[t].color]=1;}
        return;
    }
    int mid=MID(tree[t].l,tree[t].r);
    if(r<=mid) query_tree(l,r,l(t));
    else if(l>mid) query_tree(l,r,r(t));
    else
    {
        query_tree(l,mid,l(t));
        query_tree(mid+1,r,r(t));
    }
    return;
}
int main()
{
    cin>>ncase;
    while(ncase--)
    {
        int k=discretize();
        build_tree(1,k,1);
        int color=0;
        for(int i=0;i<n*2;i+=2)
        {
            color++;
            Update_tree(result[i],result[i+1],1,color);
        }
        memset(visit,0,sizeof(visit));
        cnt=0;
        query_tree(1,k,1);
        printf("%d\n",cnt);
    }
    return 0;
}

未完待续。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值