线段树

来源:互联网 发布:什么软件可以构图 编辑:程序博客网 时间:2024/05/18 10:11

线段树的模板,基本包括线段树的各个算法了吧。

#include<stdio.h>#include<iostream>using namespace std;                /**覆盖区间长度!!**/                                    /**覆盖区间数统计!!**/long aLeft[10000],aRight[10000],aLow[10000],aHigh[10000],aSum[10000],aFather[10000],len = 0,root = 1;long aChange[10000];            /**aChange[i]是结点i的改变量**/int aCord[10000],aLow_terminal[10000],aHigh_terminal[10000];void build(long a,long b)           /**创建原始的线段树**/{    long m;    len = len+1;    aLow[len] = a;    aHigh[len] = b;    if(a == b-1) return;   /**对每一个结点的Low,High值,所取的区间为(Low,High]**/                           /**即为[Low+1,High]**/                                 /**所以每次构建长度为1..L的线段树时,应为build(0,L);**/    m = len;    aLeft[m] = len+1;    //aFather[len+1] = m;    build(a,(a+b)/2);    aRight[m] = len+1;    //aFather[len+1] = m;    build((a+b)/2,b);    return;}void change(long i,long a,long b,long k)            /**增减(a,b)区间的值**/{    long mid = (aHigh[i]+aLow[i])/2;    if((aLow[i] == a-1)&&(aHigh[i] == b))    {        aChange[i] += k;        aCord[i] = 1;  /**计算覆盖区间长度**/        aLow_terminal[aLow[i]] = 1;        aHigh_terminal[aHigh[i]] = 1;        return;    }else if(a > mid)    {        aSum[i] += k*(b-a+1);        change(aRight[i],a,b,k);    }    else if(b <= mid)    {        aSum[i] += k*(b-a+1);        change(aLeft[i],a,b,k);    }    else    {        aSum[i] += k*(b-a+1);        change(aLeft[i],a,mid,k);        change(aRight[i],mid+1,b,k);    }    return;}long quiry(long i,long a)           /**查询a这一点的值**/{    long mid = (aHigh[i]+aLow[i])/2;    if((aLow[i] == a-1)&&(aHigh[i] == a)) return aChange[i];    if(a <= mid)        return aChange[i] + quiry(aLeft[i],a);    else        return aChange[i] + quiry(aRight[i],a);}long sum(long i,long a,long b)          /**计算(a,b)区间的总和**/{    long mid = (aHigh[i]+aLow[i])/2;    if((aLow[i] == a-1)&&(aHigh[i] == b))        return aChange[i]*(b-a+1)+aSum[i];    //if((a == b)&&(aHigh[i] == b))        //return aChange[i]+aSum[i];    if(b <= mid)        return aChange[i]*(b-a+1)+sum(aLeft[i],a,b);    else if (a > mid)        return aChange[i]*(b-a+1)+sum(aRight[i],a,b);    else        return aChange[i]*(b-a+1)+sum(aLeft[i],a,mid)+sum(aRight[i],mid+1,b);}long min(long a,long b){    if(a < b) return a;    else return b;}long find_min(long i,long a,long b)         /**查找(a,b)区间中的一点最小值**/{    long mid = (aHigh[i]+aLow[i])/2;    if(a == b-1) return aChange[i];    if((aLow[i] == a-1)&&(aHigh[i] == b))        return aChange[i]+min(find_min(aLeft[i],a,mid),find_min(aRight[i],mid+1,b));    if(b <= mid)        return aChange[i]+find_min(aLeft[i],a,b);    else if(a > mid)        return aChange[i]+find_min(aRight[i],a,b);    else        return aChange[i]+min(find_min(aLeft[i],a,mid),find_min(aRight[i],mid+1,b));}long count_length(long i){    long l = 0;    if(aCord[i] == 1)        return aHigh[i]-aLow[i];    if(aLeft[i] > 0)         l += count_length(aLeft[i]);    if(aRight[i] > 0)         l += count_length(aRight[i]);    return l;}long count_total(long i){    if(i == 0) return 0;    if(aCord[i] == 1)    {        if(aLow_terminal[aLow[i]] == 1 && aHigh_terminal[aLow[i]] == 0)            return 1;        return 0;    }else    {        long m;        m = count_total(aLeft[i])+count_total(aRight[i]);        return m;    }}int main(){    long k = 0;    build(0,1000);    change(root,50,98,1);    //change(root,100,150,1);    change(root,100,120,1);    //change(root,110,128,1);    change(root,124,130,1);    change(root,139,150,1);    //change(root,160,170,1);    //change(root,190,200,1);    //change(root,191,199,1);    /**cout<<k<<endl;    k = quiry(root,122);    cout<<k<<endl;    k = quiry(root,100);    cout<<k<<endl;**/    k = sum(root,100,130);    cout<<k<<endl;    /**k = find_min(root,100,120);    cout<<k<<endl;**/    k = count_length(root);    cout<<k<<endl;    k = count_total(root);    cout<<k<<endl;    system("pause");    return 0;}