正文

线段树的应用PKU32642008-08-21 12:31:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lqf110/37754.html

分享到:

#include <iostream>using namespace std;typedef struct{    int lbound, rbound;    int left, right;    int minnum, maxnum;}TreeNode;class SegmentTree{    public:        int nodenum;        TreeNode* tree;    public:        SegmentTree ( int );        void build ( int, int );        void insert ( int, int );        void search ( int, int, int);        virtual ~SegmentTree() {delete[]tree;}};//当区间长度小于128时采用顺序查找,以减少递归带来的开销const int len = 128;//存储区间权重int ary[50010];//最大最小值int Max;int Min;SegmentTree::SegmentTree ( int a ){    tree = new TreeNode[2*a+10];    memset ( tree, 0, sizeof ( TreeNode ) * ( 2*a+10 ) );    nodenum = 0;    build ( 1, a );}void SegmentTree::build ( int a, int b ){    nodenum++;    int v, mid;    v = nodenum;    tree[v].lbound = a;    tree[v].rbound = b;    tree[v].minnum = INT_MAX;    tree[v].maxnum = INT_MIN;    if ( ( b-a ) >= 1 ){        mid = (a+b)>>1;        tree[v].left = nodenum+1;        build ( a, mid );        tree[v].right = nodenum+1;        build ( mid+1, b );    }}//典型的二分插入,中值在左边void SegmentTree::insert ( int i, int a ){    int mid,f;    f = 1;    while ( 1 )    {        if ( a > tree[f].maxnum )            tree[f].maxnum = a;        if ( a < tree[f].minnum )            tree[f].minnum = a;        if ( ( tree[f].rbound-tree[f].lbound ) == 0 ) break;        mid = ( tree[f].lbound+tree[f].rbound ) >>1;        if ( i > mid ) f = tree[f].right;        else f = tree[f].left;    }}//顺序查找void Find ( int s, int e){    int i;    for ( i = s; i <= e; ++i ){        if ( ary[i] < Min )            Min = ary[i];        if ( ary[i] > Max )            Max = ary[i];    }}//递归查询void SegmentTree::search ( int s, int e, int f ){    int v, mid;    v = f;    //如果此区间的最大最小值不比当前的最大最小值更优, 返回    if ( Min <= tree[v].minnum && Max >= tree[v].maxnum ) return;    //如果当前的区间刚好覆盖始点与终点,直接查询    if ( s == tree[v].lbound && e == tree[v].rbound ){        if ( Min > tree[v].minnum ) Min = tree[v].minnum;        if ( Max < tree[v].maxnum ) Max = tree[v].maxnum;        return;    }     //砍掉区间左右两边的区间    if((s < tree[v].lbound) && ((tree[v].lbound-s) <= len)){        Find(s, tree[v].lbound-1);        s = tree[v].lbound;    }    if((e > tree[v].rbound) && ((e-tree[v].rbound)<=len)){        Find(tree[v].rbound+1, e);        e = tree[v].rbound;    }    if ( e-s <= len ) Find( s, e);    else{        if ( s == tree[v].lbound && e == tree[v].rbound ){            if ( Min > tree[v].minnum ) Min = tree[v].minnum;            if ( Max < tree[v].maxnum ) Max = tree[v].maxnum;        }        else{            mid = ( tree[v].lbound+tree[v].rbound ) >>1;            //查询的区间在当前结点的左子树上            if ( e <= mid )                search ( s, e, tree[v].left);            //查询的区间在当前结点的右子树上            else if ( s > mid )                search ( s, e, tree[v].right);            //在左右子树上查询            else{                search ( s, mid, tree[v].left);                search ( mid+1, e, tree[v].right);            }        }    }}int main ( int argv, char* argc[] ){    int vex, opt, i, num;    int f, s;    while ( scanf ( "%d%d", &vex, &opt ) != EOF ){        SegmentTree tree ( vex );        for ( i = 1; i <= vex; ++i ){            scanf ( "%d", &num );            ary[i] = num;            tree.insert ( i, num );        }        for ( i = 0; i < opt; ++i ){            Min = INT_MAX;            Max = INT_MIN;            scanf ( "%d %d", &f, &s );            if ( s - f <= len ) Find ( f, s);            else tree.search ( f, s, 1);            printf ( "%d\n", Max-Min );        }    }    return 0;}

阅读(4388) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册