敵兵布陣 1166 HDU 線段樹

2021-06-01 06:01:23 字數 1871 閱讀 4423

花了乙個下午理解了線段樹的演算法,然後開始做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是這個線段上的人數和。

然後是定義線段數的建構函式:

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)

完整**:

#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是300...

線段樹 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國都掌握的一清二楚,每個工兵營地的人數都有可能發生...