初識演算法,花了乙個下午理解了線段樹的演算法,然後開始做hdu上的1166題。
先說說對於線段樹的乙個理解:
比如要在自然數,且所有的數不大於30000的範圍內討論乙個問題:現在已知n條線段,把端點依次輸入告訴你,然後有m個(多次)詢問,每個詢問輸入乙個點,要求這個點在多少條線段上出現過;
假如m是30000,那麼計算量達到了10^9;而計算機1秒的計算量大約是10^8的數量級,所以這種方法無論怎麼優化都是超時
因為n條線段是固定的,所以某種程度上說每次都把n條線段查一遍有大量的重複和浪費;
線段樹就是可以解決這類問題的資料結構。
類似於二叉樹,有構造,插入,修改的方法。
關鍵是要設定乙個結構體,來存放不同的線段,然後依次往後構造或者修改。其中關鍵是左兒子的標識是父親標識×2,右兒子的標識是父親標識×2+1.還是用hdu的1166來說明下:
題目描述:
第一行乙個整數t,表示有t組資料。
每組資料第一行乙個正整數n(n<=50000),表示敵人有n個工兵營地,接下來有n個正整數,第i個正整數ai代表第i個工兵營地里開始時有ai個人(1<=ai<=50)。
接下來每行有一條命令,命令有4種形式:
(1) add i j,i和j為正整數,表示第i個營地增加j個人(j不超過30)
(2)sub i j ,i和j為正整數,表示第i個營地減少j個人(j不超過30);
(3)query i j ,i和j為正整數,i<=j,表示詢問第i到第j個營地的總人數;
(4)end 表示結束,這條命令在每組資料最後出現;
每組資料最多有40000條命令
要求:對第i組資料,首先輸出「case i:」和回車,
對於每個query詢問,輸出乙個整數並回車,表示詢問的段中的總人數,這個數最多不超過1000000。
首先我們建立乙個結構體:
struct
t[140000];
其中a,b是線段的座標,sum是這段線段上key的和;
然後是定義線段數的建構函式:
int r[50010],sum; //r[50010]是存放每個點上的人數,sum是用來存放查詢的結果。
void make(int x,int y,int num)
}
定義查詢函式:
void query(int x,int y,int num)
} }
定義add函式:
void add(int x,int y,int num)
定義sub函式:
view plain
void sub(int x,int y,int num)
下面附帶完整**:
#includeusing namespace std;
struct
t[140000];
int r[50010],sum; //r[50010]是存放每個點上的人數,sum是用來存放查詢的結果。
void make(int x,int y,int num)
}void query(int x,int y,int num) }}
void add(int x,int y,int num)
void sub(int x,int y,int num)
int main(int argc, char* argv)
else if(strcmp(command,"sub")==0)
}} return 0;
}
敵兵布陣 1166 HDU 線段樹
花了乙個下午理解了線段樹的演算法,然後開始做hdu上的1166題。先說說對於線段樹的乙個理解 比如要在自然數,且所有的數不大於30000的範圍內討論乙個問題 現在已知n條線段,把端點依次輸入告訴你,然後有m個 多次 詢問,每個詢問輸入乙個點,要求這個點在多少條線段上出現過 假如m是30000,那麼計...
線段樹 hdu1166 敵兵布陣
problem description c國的死對頭a國這段時間正在進行軍事演習,所以c國間諜頭子derek和他手下tidy又開始忙乎了。a國在海岸線沿直線布置了n個工兵營地,derek和tidy的任務就是要監視這些工兵營地的活動情況。由於採取了某種先進的監測手段,所以每個工兵營地的人數c國都掌握的...
敵兵布陣 HDU 1166 線段樹
c國的死對頭a國這段時間正在進行軍事演習,所以c國間諜頭子derek和他手下tidy又開始忙乎了。a國在海岸線沿直線布置了n個工兵營地,derek和tidy的任務就是要監視這些工兵營地的活動情況。由於採取了某種先進的監測手段,所以每個工兵營地的人數c國都掌握的一清二楚,每個工兵營地的人數都有可能發生...