線段樹可以說是每次比賽中必出的題了,但是線段樹好難,我太難了,我上輩子一定是一道線段樹的題。
下面是一些基礎線段樹的題目,入門必備。。。
線段樹是一種二叉搜尋樹,將原始資料都存在葉節點,依次表示出每個葉節點的根節點。
一般陣列開到葉節點數量的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 ...