• ACM数据结构-线段树


    1.维护区间最大最小值模板(以维护最小值为例)

    #include<iostream> 
    #include<stdio.h>
    
    #define LEN 11
    #define MAX 1<<30
    
    using namespace std;
    
    int arr[LEN]={1,3,7,6,8,5,3,2,7,2,9};
    int st[LEN*3];    //segment tree
    int n;
    
    void init(int len){
        n=1;
        while(n<len) n*=2;    //不断乘以2,知道>=len
        for(int i=0;i<n;i++) st[i]=MAX;
    }
    
    void update(int p,int v){    //我们有n(len的二次幂扩增)个叶子作为线段元素 
        p+=n-1;            //地址重定向,变为叶子节点所在地址
        st[p]=v;
        while(p>0){
            p=(p-1)/2;    //向上跳转到父节点
            st[p]=min(st[p*2+1],st[p*2+2]);    //更新父节点 
        } 
    }
    
    //    查询[a,b)的最小值,当前函数的查询是[l,r) 。当前根节点为p 
    int query(int a,int b,int p,int l,int r){//外部调用: query(a,b,0,0,n)
        //如果[a,b)与[l,r)不相交
        if(a>=r || b<=l)
            return MAX;
        //如果[a,b)包裹住了[l,r)
        if(a<=l && b>=r)
            return st[p];
        //其他情况,二分进行查询 
        int v1=query(a,b,p*2+1,l,(l+r)/2);
        int v2=query(a,b,p*2+2,(l+r)/2,r);
        return min(v1,v2);
    } 
    
    int main(){
        init(LEN);
        int i,a,b;
        for(i=0;i<LEN;i++)
            update(i,arr[i]);
        while(1){
            scanf("%d%d",&a,&b);
            printf("%d
    ",query(a,b,0,0,n));
        }
        return 0;
    } 

    2.维护区间和的模板

    数据结构:

    struct node
    {
        int left,right;
        int num;
    }tree[2000010];

    建树:

    void build(int left,int right,int index)    //build(1,n,1);
    {
        he++;
        tree[index].left=left;
        tree[index].right=right;
        if(left==right)
            return ;
        int mid=(right+left)/2;
        build(left,mid,index*2);
        build(mid+1,right,index*2+1);
    }

    单点修改:

    void my_plus(int index,int dis,int k)    //将索引为p的元素增加k 
    {                                        // my_plus(1,p,k)
        tree[index].num+=k;
        if(tree[index].left==tree[index].right)    //没有叶子节点 
            return ;
        if(dis<=tree[index*2].right)
            my_plus(index*2,dis,k);
        if(dis>=tree[index*2+1].left)
            my_plus(index*2+1,dis,k);
    }

    单点查询:

    int search(int index,int dis) //调用方法:查找索引为p的元素:search(1,p)
    {
        if(tree[index].left==tree[index].right && tree[index].left==dis)
            return tree[index].num;
        if(dis<=tree[index*2].right)
            search(index*2,dis);
        if(dis>=tree[index*2+1].left)
            search(index*2+1,dis);
    }

    区间修改:

        void pls(int index,int l,int r,int k)
        {
            if(tree[index].left>=l && tree[index].right<=r)
            {
                tree[index].num+=k;
                return ;
            }
            if(tree[index*2].right>=l)
               pls(index*2,l,r,k);
            if(tree[index*2+1].left<=r)
               pls(index*2+1,l,r,k);
        }

    区间查询:

    void search(int index,int l,int r)
    {
        //cout<<index<<" ";
        if(tree[index].left>=l && tree[index].right<=r)
        {
            ans+=tree[index].num;
            return ;
        }
        if(tree[index*2].right>=l)
            search(index*2,l,r);
        if(tree[index*2+1].left<=r)
            search(index*2+1,l,r);
    }

    3.模板编写练习:

  • 相关阅读:
    图像按钮
    提交按钮
    文件上传域
    Python创建虚拟环境
    Typecho使用技巧
    面向对象
    Python语法入门
    Python 基础数据类型
    与用户交互
    MySQL5.7安装教程
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8449528.html
Copyright © 2020-2023  润新知