線段樹

線段樹的模板,基本包括線段樹的各個算法了吧。

#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;

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章