zoukankan      html  css  js  c++  java
  • 数据结构之线段树

    线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

    对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。

    因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。

    用线段树解题关键是要清楚的知道每个节点要存放什么信息,以及这些节点如何高效的更新,维护,查询,不一定每次都更新到叶子节点,这样复杂度最坏有可能是0(n)

    下面附上一道题

    poj3264

    思路:用一维数组存放节点,节点数<=4n-1,每个节点存放该区间的最大值,最小值

    代码

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    int minV=INF;
    int maxV=-INF;
    //节点信息

    struct Note
    {
        int L,R;
        int minV,maxV;
        int Mid()
        {
            return (L+R)/2;
        }
    };Note tree[800010];

    //建树
    void buildtree(int root,int L,int R)
    {
        tree[root].L=L;
        tree[root].R=R;
        tree[root].minV=INF;
        tree[root].maxV=-INF;
        if(L!=R)
        {
            buildtree(root*2+1,L,(L+R)/2);
            buildtree(root*2+2,(L+R)/2+1,R);
        }
    }

    //插入
    void insert(int root,int i,int v)
    {
        if(tree[root].L==tree[root].R)
        {
            tree[root].minV=tree[root].maxV=v;
            return ;
        }
        tree[root].minV=min(v,tree[root].minV);
        tree[root].maxV=max(v,tree[root].maxV);
        if(i<=tree[root].Mid())
        {
            insert(2*root+1,i,v);
        }
        else
        {
            insert(2*root+2,i,v);
        }
    }

    //查询
    void chaxun(int root,int s,int e)
    {
        if(tree[root].minV>=minV&&tree[root].maxV<=maxV)
        {
            return ;
        }
        if(tree[root].L==s&&tree[root].R==e)
        {
            minV=min(minV,tree[root].minV);
            maxV=max(maxV,tree[root].maxV);
            return ;
        }
        if(e<=tree[root].Mid())
        {
            chaxun(2*root+1,s,e);
        }
        else if(s>tree[root].Mid())
        {
            chaxun(2*root+2,s,e);
        }
        else
        {
            chaxun(2*root+1,s,tree[root].Mid());
            chaxun(2*root+2,tree[root].Mid()+1,e);
        }
    }
    int main()
    {
        int p,n;
        int i,h;
        while(scanf("%d%d",&n,&p)!=-1)
        {
            buildtree(0,1,n);
            for(i=1;i<=n;i++)
            {
                scanf("%d",&h);
                insert(0,i,h);
            }
            for(i=0;i<p;i++)
            {
                int s,e;
                scanf("%d%d",&s,&e);
                minV=INF;
                maxV=-INF;
                chaxun(0,s,e);
                printf("%d ",maxV-minV);
            }
        }
        return 0;

  • 相关阅读:
    测试工作——XML
    js call apply
    JavaScript 作用域和作用域链
    hybird app
    正则表达式
    浏览器渲染原理
    head 头标签(转发)
    参考资料地址
    unix 常用命令
    phantomjs 自动化测试
  • 原文地址:https://www.cnblogs.com/ACWQYYY/p/4390501.html
Copyright © 2011-2022 走看看