线段树

来源:互联网 发布:windows jdk版本升级 编辑:程序博客网 时间:2024/06/11 03:20
//poj1166 求区间连续和#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std ;const int maxn = 1e6;/* 线段树通过将线段离散化构建了一颗二叉查找树的树结构,类似于完全二叉树使用数组实现离线算法,在logn内完成对区间点的四则运算等值更新,以及区间最值连续和等区间问题和区间某点问题的操作线段树叶节点是 [a,a]的点区间,中间节点可以存放中间结果,他是完成了对子节点的操作,可以直接使用中间节点的值,这就是在比较的时候使用 if (ll <= l && rr >= r) return sum[rt] 的原因,从而避免了访问rt叶节点,增加复杂度 */  //线段树的节点定义,左右边界和区间结果数值,这种定义可以多添加几个区间结果数值,比如区间连续和和区间最值 struct seg{    int l , r , val ;}T[maxn];//预先构建线段树// m >> 1 | 1 等于 m / 2 + 1 void build( int l , int r , int pos){    if( l == r){        T[pos].l = l ;        T[pos].r = r ;        T[pos].val = 0 ;        return ;    }    int mid = (l + r ) >> 1  ;    T[pos].l = l ;    T[pos].r = r ;    T[pos].val = 0 ;    //左子区间     build(l , mid , pos << 1) ;    //右子区间     build(mid + 1 , r , pos << 1 | 1) ;} void ins( int n , int d , int k ){    //d子区间,不是第d个,而是区间边界是d     if( T[k].l == T[k].r && T[k].l == d ){        T[k].val += n ;        return ;    }    int mid = ( T[k].l  + T[k].r ) >> 1 ;    if( d <= mid) ins( n , d , k<< 1) ;    else         ins( n , d , k<<1 | 1) ;    //父节点的区间值来源于两个子区间的区间值     T[k].val = T[ k << 1].val + T[ k << 1 | 1].val ; }int query( int l , int r , int k ){    //线段树使用的左闭右闭的区间     //当区间[l,r]包含k区间[T[k].l , T[k].r ] 的时候, 区间[l,r] 的区间值可以来源于k区间     if( l <= T[k].l && r>= T[k].r )        return T[k].val ;    int ans = 0 ;    int mid = ( T[k].l + T[k].r ) >> 1  ;    //k区间的左子区间为[T[k].l , mid ] , 右子区间为[mid + 1 , T[k].r ]     //当l<=mid 则证明[l,r] 区间在左子区间有来源 ,去左子区间区间值     if( l <=mid )        ans += query( l , r , k << 1) ;    //因为右子区间范围[mid + l, T{k],r ] ,则证明区间[l,r] 在右子区间有来源,取右子区间区间值     if( r > mid )         ans += query( l , r , k << 1 | 1) ;    //父区间[l,r] 的区间值为ans      return ans ;}int main(){    int a;    scanf("%d",&a) ;    for(int i = 1 ;i<= a ;i++){        int b ;        scanf("%d"  , & b) ;        //父区间下标序号为1 , 区间边界[1 , b]          build( 1 , b , 1) ;        for(int j = 1 ; j <= b ; j++){            int temp ;            scanf("%d", & temp) ;            ins( temp , j , 1) ;         }         printf("Case %d:\n" , i) ;        char s[11] ;        while(scanf("%s" , s) && s[0]!='E' ) {            int c , d;            scanf("%d%d" , & c , & d) ;            if( s[0] == 'A') ins( d , c , 1) ;            else if( s[0] == 'S')                ins( -d , c , 1) ;            else{                int ans = query ( c, d , 1) ;                printf("%d\n" , ans) ;            }        }     }    return 0 ;} 
原创粉丝点击