線段樹例題

2021-08-24 18:01:28 字數 4849 閱讀 5541

線段樹可以說是每次比賽中必出的題了,但是線段樹好難,我太難了,我上輩子一定是一道線段樹的題。

下面是一些基礎線段樹的題目,入門必備。。。

線段樹是一種二叉搜尋樹,將原始資料都存在葉節點,依次表示出每個葉節點的根節點。

一般陣列開到葉節點數量的4倍。

關於線段樹的例題

。hdu1166 敵兵布陣

按照指示來就可以

**

#include

#include

#include

#include

using namespace std;

#define m 50005

int n;

int a[m]

;int sum[m<<2]

,add[m<<2]

;//n<<2表示n*4;

void

pushup

(int rt)

void

build

(int l,

int r,

int rt)

int m=

(l+r)

>>1;

build

(l,m,rt<<1)

;//建立左支樹

build

(m+1

,r,rt<<1|

1);//建立右支樹

pushup

(rt);}

void

update

(int l,

int c,

int l,

int r,

int rt)

//l為要修改的位置,c指要修改的值

int m=

(l+r)

>>1;

if(l <= m)

update

(l,c,l,m,rt<<1)

;else

update

(l,c,m+

1,r,rt<<1|

1);pushup

(rt);}

intquery

(int l,

int r,

int l,

int r,

int rt)

int m=

(l+r)

>>1;

int ans=0;

if(l <= m) ans+

=query

(l,r,l,m,rt<<1)

;if(r > m) ans+

=query

(l,r,m+

1,r,rt<<1|

1);return ans;

}int

main()

else

if(op[0]

=='s'

)else}}

return0;

}

。hdu1754 i hate it

同樣按照要求即可

不同的是上一題是求和,而這一題是要求求出最大的數,所以在根據子節點求根節點的時候要用max

**

#include

#include

using namespace std;

#define m 200005

int sum[m<<2]

;void

pushup

(int rt)

void

build

(int l,

int r,

int rt)

else

}void

update

(int l,

int c,

int l,

int r,

int rt)

else

}int

query

(int l,

int r,

int l,

int r,

int rt)

int m=

(l+r)

>>1;

int ans=0;

if(l <= m) ans=

max(ans,

query

(l,r,l,m,rt<<1)

);//求最大

if(r > m) ans=

max(ans,

query

(l,r,m+

1,r,rt<<1|

1));

return ans;

}int

main()

else

if(c[0]

=='u')}

}return0;

}

。hdu1698 just a hook

題意:原來有n個數,都為1,現在對他們進行改變,每次操作輸入x,y,z,代表把【x,y】的值全部改變為z,z可以是1,2,3。

最後輸出n個數的和。

**

#include

#include

using namespace std;

#define m 100005

int sum[m<<2]

;int init[m<<2]

;//用來存原始資料

void

pushup

(int rt)

void

build

(int l,

int r,

int rt)

int m=

(l+r)

>>1;

build

(l,m,rt<<1)

;build

(m+1

,r,rt<<1|

1);pushup

(rt);}

void

pushdown

(int rt,

int ln,

int rn)

//下推標記節點,ln,rn表示左子樹,右子樹的資料數量

}void

update

(int l,

int r,

int c,

int l,

int r,

int rt)

//要修改的是乙個區間的值,所以要進行標記,l,r為該區間的左右端點

int m=

(l+r)

>>1;

pushdown

(rt,m-l+

1,r-m)

;//下推標記

if(l <= m)

update

(l,r,c,l,m,rt<<1)

;if(r > m)

update

(l,r,c,m+

1,r,rt<<1|

1);pushup

(rt);}

intmain()

else

if(z ==2)

else

}int ans=sum[1]

;//sum[1]即為所有數的和

printf

("case %d: the total value of the hook is %d.\n"

,++k,ans);}

return0;

}

。codeforces 91b queue

有n只海象排隊,第一只站在最後的位置,第n只站在第一的位置(從左到右),第i只海象的年齡為ai,找站在他右邊的海象中比他年輕的且離他最遠的和他之間有多少只海象,(注意即使離他最遠的比他年輕的海象和他之間有年紀比他大的也不會停,知道找到最右端那個比他小的),不存在輸出-1。

還可以用vector做,單調佇列,從第n個數開始遍歷

**

#include

#include

using namespace std;

#define m 200005

#define maxn 100000005

//定義乙個很大的值來標記已經遍歷過的資料

int sum[m<<2]

,a[m<<2]

;void

pushup

(int rt)

void

build

(int l,

int r,

int rt)

int m=

(l+r)

>>1;

build

(l,m,rt<<1)

;build

(m+1

,r,rt<<1|

1);pushup

(rt);}

void

update

(int l,

int l,

int r,

int rt)

int m=

(l+r)

>>1;

if(l <= m)

update

(l,l,m,rt<<1)

;else

update

(l,m+

1,r,rt<<1|

1);pushup

(rt);}

intquery

(int x,

int l,

int r,

int rt)

int m=

(l+r)

>>1;

if(sum[rt<<1|

1]< x)

query

(x,m+

1,r,rt<<1|

1);else

query

(x,l,m,rt<<1)

;}intmain()

return0;

}

例題 線段樹

1 注意討論不能建樹的情況 nkoj 1321 數列操作問題 時間限制 10000 ms 空間限制 165536 kb 問題描述 假設有一列數 1 i n 支援如下兩種操作 將ak的值加d。k,d是輸入的數 輸出as as 1 at。s,t都是輸入的數,s t 輸入格式 第一行乙個整數n,第二行為n...

例題 線段樹 lazy

1 1 lazy思想 對整個結點進行的操作,先在結點上做標記,而並非真正執行,直到根據查詢操作的需要分到下層。2 延遲標記 lazy 如果需要對乙個區間中每乙個葉結點進行操作,我們不妨先別忙著操作,而是在所有大區間上做乙個標記,下一次遇到或要用到時,再進行處理 標記傳遞 達到減少操作次數,提高線段樹...

線段樹 模板 例題

模板 以區間和為例。ll ls ll p ll rs ll p void push up ll p void build ll p,ll l,ll r ll mid l r 1 build ls p l,mid build rs p mid 1 r push up p void f ll p,ll ...