線段樹的模板,基本包括線段樹的各個算法了吧。
#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;
}