![線段樹(shù)線段樹(shù)和樹(shù)狀數(shù)組_第1頁(yè)](http://file4.renrendoc.com/view/ded8c4cb46905ca0385e4e10d2a47670/ded8c4cb46905ca0385e4e10d2a476701.gif)
![線段樹(shù)線段樹(shù)和樹(shù)狀數(shù)組_第2頁(yè)](http://file4.renrendoc.com/view/ded8c4cb46905ca0385e4e10d2a47670/ded8c4cb46905ca0385e4e10d2a476702.gif)
![線段樹(shù)線段樹(shù)和樹(shù)狀數(shù)組_第3頁(yè)](http://file4.renrendoc.com/view/ded8c4cb46905ca0385e4e10d2a47670/ded8c4cb46905ca0385e4e10d2a476703.gif)
![線段樹(shù)線段樹(shù)和樹(shù)狀數(shù)組_第4頁(yè)](http://file4.renrendoc.com/view/ded8c4cb46905ca0385e4e10d2a47670/ded8c4cb46905ca0385e4e10d2a476704.gif)
![線段樹(shù)線段樹(shù)和樹(shù)狀數(shù)組_第5頁(yè)](http://file4.renrendoc.com/view/ded8c4cb46905ca0385e4e10d2a47670/ded8c4cb46905ca0385e4e10d2a476705.gif)
下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
課程網(wǎng)頁(yè)http
/JudgeOnline/summerschool/pku_acm_train.htm上機(jī)地點(diǎn):理科1號(hào)樓1235線段樹(shù)和樹(shù)狀數(shù)組信息學(xué)院線段樹(shù)(Interval
Tree)實(shí)際上還是稱為區(qū)間樹(shù)更好理解一些。樹(shù):是一棵樹(shù),而且是一棵二叉樹(shù)。線段:樹(shù)上的每個(gè)節(jié)點(diǎn)對(duì)應(yīng)于一個(gè)線段(還是叫
“區(qū)間”更容易理解,區(qū)間的起點(diǎn)和終點(diǎn)通常為整數(shù))同一層的節(jié)點(diǎn)所代表的區(qū)間,相互不會(huì)
。葉子節(jié)點(diǎn)的區(qū)間是單位長(zhǎng)度,不能再分了。線段樹(shù)是一棵二叉樹(shù),樹(shù)中的每一個(gè)結(jié)點(diǎn)表示了一個(gè)區(qū)間[a,b]。a,b通常是整數(shù)。每一個(gè)葉子節(jié)點(diǎn)表示了一個(gè)單位區(qū)間。對(duì)于每一個(gè)非葉結(jié)點(diǎn)所表示的結(jié)點(diǎn)[a,b],其左兒子表示的區(qū)間為[a,(a+b)/2],右兒子表示的區(qū)間為[(a+b)/2+1,b](除法去尾取整)。區(qū)間[1,
9]的線段樹(shù)[1,9][1,5][6,9][1,3]3[1,2][4,5]
[6,7]
[8,9]4
5
6
7
891
2每個(gè)區(qū)間的長(zhǎng)度是區(qū)間內(nèi)整數(shù)的個(gè)數(shù)葉子節(jié)點(diǎn)長(zhǎng)度為1,不能再往下分若一個(gè)節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間是[a,b],則其子節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間分別是[a,(a+b)/2]和[(a+b)/2+1,b](除法去尾取整)線段樹(shù)的平分構(gòu)造,實(shí)際上是用了二分的方法。若根節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間是[a,b],那么它的深度為log2(b-a+1)
+1
(向上取整)。葉子節(jié)點(diǎn)的數(shù)目和根節(jié)點(diǎn)表示區(qū)間的長(zhǎng)度相同.線段樹(shù)是滿二叉樹(shù)(節(jié)點(diǎn)要么0度,要么2度),因此若葉子節(jié)點(diǎn)數(shù)目為N,則線段樹(shù)總結(jié)點(diǎn)數(shù)目為2N-1區(qū)間[1,
9]的線段樹(shù)上,區(qū)間[2,8]的分解[1,9][1,5]
[6,9][1,3]
[4,5]
[6,7]
[8,9]34
5
6
7
8[1,2]
91
2分解的規(guī)則就是:如果有某個(gè)節(jié)點(diǎn)代表的區(qū)間,完全屬于待分解區(qū)間,則該節(jié)點(diǎn)為“終止”節(jié)點(diǎn),不再繼續(xù)往下分解所有“終止”節(jié)點(diǎn)所代表的區(qū)間都不
,且加在一起就覆蓋了整條待分解區(qū)間區(qū)間[1,
9]的線段樹(shù)上,區(qū)間[2,8]的分解[1,9][1,5]
[6,9][1,3]
[4,5]
[6,7]
[8,9]34
5
6
7
8[1,2]
91
2區(qū)間分解的時(shí)候,每層最多2個(gè)“終止節(jié)點(diǎn)”,所以終止節(jié)點(diǎn)總數(shù)也是log(n)量級(jí)的證明每層最多2個(gè)“終止節(jié)點(diǎn)”:[a,b][c,d][e,f]X代表終止節(jié)點(diǎn)。上述情況不可能發(fā)生線段樹(shù)的特征1、線段樹(shù)的深度不超過(guò)log2(n)+1(向上取整,n是根節(jié)點(diǎn)對(duì)應(yīng)區(qū)間的長(zhǎng)度)。2、線段樹(shù)上,任意一個(gè)區(qū)間被分解后得到的“終止節(jié)點(diǎn)”數(shù)目都是log(n)量級(jí)。線段樹(shù)上更新葉子節(jié)點(diǎn)和進(jìn)行區(qū)間分解時(shí)間復(fù)雜度都是O(log(n))的這些結(jié)論為線段樹(shù)能在O(log(n))的時(shí)間內(nèi)完成一個(gè)區(qū)間的建樹(shù),
數(shù)據(jù),查找、統(tǒng)計(jì)等工作,提供了理論依據(jù)線段樹(shù)的構(gòu)建function
以節(jié)點(diǎn)v為根建樹(shù)、v對(duì)應(yīng)區(qū)間為[l,r]{對(duì)節(jié)點(diǎn)v初始化if
(l!=r){以v的左孩子為根建樹(shù)、區(qū)間為[l,(l+r)/2]以v的右孩子為根建樹(shù)、區(qū)間為[(l+r)/2+1,r]}}線段樹(shù)的基本用途線段樹(shù)適用于和區(qū)間統(tǒng)計(jì)有關(guān)的問(wèn)題。比如某些數(shù)據(jù)可以按區(qū)間進(jìn)行劃分,按區(qū)間動(dòng)態(tài)進(jìn)行修改,而且還需要按區(qū)間多次進(jìn)行查詢,那么使用線段樹(shù)可以達(dá)到較快查詢速度。線段樹(shù)應(yīng)用舉例給你一個(gè)數(shù)的序列A1A2……An。并且可能多次進(jìn)行下列兩個(gè)操作:1、對(duì)序列里面的某個(gè)數(shù)進(jìn)行加減2、詢問(wèn)這個(gè)序列里面任意
續(xù)的子序列AiAi+1……Aj的和是多少。希望第2個(gè)操作每次能在log(n)時(shí)間內(nèi)完成線段樹(shù)應(yīng)用舉例顯然,[1,n]就是根節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間可以在每個(gè)節(jié)點(diǎn)記錄該節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間里面的數(shù)的和Sum。對(duì)于操作1:因?yàn)樾蛄欣锩鍭i最多只會(huì)被線段樹(shù)的log(n)個(gè)節(jié)點(diǎn)覆蓋。只要求對(duì)線段樹(shù)覆蓋
Ai的節(jié)點(diǎn)的Sum進(jìn)行加操作,因此復(fù)雜度是
log(n)對(duì)于操作2:同樣只需要找到區(qū)間所覆蓋的節(jié)點(diǎn),然后把所找節(jié)點(diǎn)的Sum累加起來(lái)。因?yàn)檫@些節(jié)點(diǎn)的數(shù)量是O(log(n))的,所以這一步的復(fù)雜度也是log(n)線段樹(shù)應(yīng)用舉例如果走到節(jié)點(diǎn)[L,R]時(shí),如果要查詢的區(qū)間就是[L,R](求AL到AR的和)那么直接返回該節(jié)點(diǎn)的Sum,并累加到總的和上;如果不是,則:對(duì)于區(qū)間[L,R],取mid=(L+R)/2;然后看要查詢的區(qū)間與[L,mid]或[mid+1,R]哪個(gè)有交集,就進(jìn)入哪個(gè)區(qū)間進(jìn)行進(jìn)一步查詢。因?yàn)檫@個(gè)線段樹(shù)的深度最深的LogN,所以每次遍歷操作都在LogN的內(nèi)完成。但是常數(shù)可能很大。線段樹(shù)應(yīng)用舉例如果是對(duì)區(qū)間所對(duì)應(yīng)的一些數(shù)據(jù)進(jìn)行修改,過(guò)程和查詢類(lèi)似。用線段樹(shù)解題,關(guān)鍵是要想清楚每個(gè)節(jié)點(diǎn)要存哪些信息(當(dāng)然區(qū)間起終點(diǎn),以及左右子節(jié)點(diǎn)指針是必須的),,查詢。不要一更新就可能變成O(n)以及這些信息如何高效更新,就更新到葉子節(jié)點(diǎn),那樣更新效率的了。先建樹(shù),然后
數(shù)據(jù),然后更新,查詢。例題:POJ
3264
Balanced
Lineup給定Q
(1≤Q
≤200,000)個(gè)數(shù)A1,A2
…AQ,,多次求任一區(qū)間Ai
–Aj中最大數(shù)和最小數(shù)的差。本題樹(shù)節(jié)點(diǎn)結(jié)構(gòu)是什么?例題:POJ
3264
Balanced
Lineup給定Q
(1≤Q
≤200,000)個(gè)數(shù)A1,A2
…AQ,,多次求任一區(qū)間Ai
–Aj中最大數(shù)和最小數(shù)的差。本題樹(shù)節(jié)點(diǎn)結(jié)構(gòu):struct
CNode{int
L,R;//區(qū)間起點(diǎn)和終點(diǎn)int
nMin,nMax;//本區(qū)間里的最大最小值CNode
*
pLeft,
*
pRight;};也可以不要左右節(jié)點(diǎn)指針,用一個(gè)數(shù)組存放線段樹(shù)。根節(jié)點(diǎn)下標(biāo)為0。假設(shè)線段樹(shù)上某節(jié)點(diǎn)下標(biāo)為i,則其左子節(jié)點(diǎn)下表為i*2+1,右子節(jié)點(diǎn)下標(biāo)為i
*
2+2即(i<<1)+1和(i<<1)+2Sample
Input6
3
//6個(gè)數(shù),3次個(gè)查詢2Sample
Output630#include
<iostream>#include
<algorithm>#include
<numeric>using
namespacestd;#define
MY_MIN
99999999#define
MY_MAX
-99999999struct
CNode{int
L,R;int
nMin,nMax;CNode
*
pLeft,
*
pRight;};int
nMax,
nMin;CNode
Tree[1000000];//其實(shí)兩倍葉子節(jié)點(diǎn)的數(shù)量就夠
int
nCount=0;//總節(jié)點(diǎn)數(shù)目void
BuildTree(CNode
*
pRoot,
int
L,int
R){pRoot->L
=L;pRoot->R=
R;pRoot->nMin
=
MY_MIN;pRoot->nMax
=
MY_MAX;if
(
L
!=
R)
{nCount
++;pRoot->pLeft
=
Tree
+
nCount;nCount
++;pRoot->pRight
=
Tree
+
nCount;BuildTree(
pRoot->pLeft,
L,
(
L
+
R
)/2);BuildTree(
pRoot->pRight,
(L
+
R)
/
2
+
1,R);}}void
Insert(
CNode*
pRoot
,
int
i,int
v)線段樹(shù)//將第i個(gè)數(shù),其值為v,{if(
pRoot->L
==
i
&&
pRoot->R
==
i
)
{pRoot->nMin
=
pRoot->nMax
=
v;return;}pRoot->nMin
=
min(pRoot->nMin,v);pRoot->nMax
=max(pRoot->nMax,v);if(
i
<=
(pRoot->L
+
pRoot->R
)/2
)Insert(
pRoot->pLeft,i,v);elseInsert(
pRoot->pRight,i,v);}void
Query(CNode
*
pRoot,
int
s,
int
e)//查詢區(qū)間[s,e]中的最小值和最大值,如果更優(yōu)就記在全局變量里{if(
pRoot->nMin
>=
nMin
&&
pRoot->nMax
<=
nMax
)return;if(
s
==
pRoot->L
&&
e
==
pRoot->R){nMin
=
min(pRoot->nMin,nMin);nMax=max(pRoot->nMax,nMax);return;}if(
e
<=
(pRoot->L
+
pRoot->R)
/
2)Query(pRoot->pLeft,
s,e);else
if(
s
>=
(pRoot->L
+pRoot->R)
/
2
+
1)Query(pRoot->pRight,
s,e);else
{Query(pRoot->pLeft,
s,(pRoot->L+
pRoot->R)
/
2);Query(pRoot->pRight,
(pRoot->L
+
pRoot->R)
/
2+1
,e);}}int
main(){int
n,q,h;int
i,j,k;scanf("%d%d",&n,&q);nCount
=
0;BuildTree(Tree,1,n);for(
i
=
1;i
<=
n;i
++
)
{scanf("%d",&h);Insert(
Tree,i,h);}for(
i
=
0;i
<
q;i
++
)
{int
s,e;scanf("%d%d",
&s,&e);nMax
=
MY_MAX;nMin
=
MY_MIN;Query(Tree,s,e);printf("%d\n",nMax
-nMin);}return
0;}POJ
3468
A
Simple
Problem
with
Integers給定Q
(1≤Q
≤100,000)個(gè)數(shù)A1,A2
…AQ,,以及可能多次進(jìn)行的兩個(gè)操作:對(duì)某個(gè)區(qū)間Ai
…Aj的每個(gè)數(shù)都加n(n可變)求某個(gè)區(qū)間Ai
…Aj的數(shù)的和本題樹(shù)節(jié)點(diǎn)要存哪些信息?只存該區(qū)間的數(shù)的和,行不行?POJ
3468
A
Simple
Problem
with
Integers只存和,會(huì)導(dǎo)致每次加數(shù)的時(shí)候都要更新到葉子節(jié)點(diǎn),速度太慢,這是必須要避免的。本題樹(shù)節(jié)點(diǎn)結(jié)構(gòu):struct
CNode{int
L
,R;//區(qū)間起點(diǎn)和終點(diǎn)CNode
*
pLeft,
*
pRight;long
longnSum;//原來(lái)的和long
long
Inc;//增量n的累加};//本節(jié)點(diǎn)區(qū)間的和實(shí)際上是nSum+Inc*(R-L+1)POJ
3468
A
Simple
Problem
with
Integers在增加時(shí),如果要加的區(qū)間正好覆蓋一個(gè)節(jié)點(diǎn),則增加其節(jié)點(diǎn)的Inc值,不再往下走,否則要更新nSum,再將增量往下傳在查詢時(shí),如果待查區(qū)間不是正好覆蓋一個(gè)節(jié)點(diǎn),就將節(jié)點(diǎn)的Inc往下帶,然后將Inc代表的所有增量累加到nSum上后將Inc清0,接下來(lái)再往下查詢。#include
<iostream>using
namespace
std;struct
CNode{int
L
,R;CNode
*
pLeft,
*
pRight;long
long
nSum;//原來(lái)的和
long
long
Inc;//增量c的累加};CNode
Tree[1000000];int
nCount
=
0;int
Mid(
CNode
*
pRoot){return
(pRoot->L
+
pRoot->R)/2;}void
BuildTree(CNode
*
pRoot,int
L,
int
R){pRoot->L
=L;pRoot->R=
R;pRoot->nSum
=
0;pRoot->Inc
=0;if(
L
==
R)return;nCount
++;pRoot->pLeft
=
Tree
+
nCount;nCount
++;pRoot->pRight
=
Tree
+
nCount;BuildTree(pRoot->pLeft,L,(L+R)/2);BuildTree(pRoot->pRight,(L+R)/2+1,R);}void
Insert(
CNode
*
pRoot,int
i,
int
v){if(
pRoot->L
==
i
&&
pRoot->R
==
i)
{pRoot->nSum
=
v;return
;}pRoot->nSum
+=
v;if(
i
<=
Mid(pRoot))Insert(pRoot->pLeft,i,v);elseInsert(pRoot->pRight,i,v);}void
Add(
CNode
*
pRoot,
int
a,
int
b,
long
long
c){if(
pRoot->L
==
a
&&
pRoot->R
==b)
{pRoot->Inc
+=
c;return;}pRoot->nSum
+=
c
*
(
b
-
a
+
1)
;if(
b<=
(pRoot->L
+
pRoot->R)/2)Add(pRoot->pLeft,a,b,c);else
if(
a
>=
(pRoot->L
+
pRoot->R)/2
+1)Add(pRoot->pRight,a,b,c);else
{Add(pRoot->pLeft,a,(pRoot->L
+
pRoot->R)/2
,c);Add(pRoot->pRight,(pRoot->L
+pRoot->R)/2
+1,b,c);}}long
long
QuerynSum(
CNode
*
pRoot,
int
a,
int
b){if(
pRoot->L
==
a
&&
pRoot->R
==
b)return
pRoot->nSum
+(pRoot->R
-
pRoot->L
+
1)*
pRoot->Inc
;pRoot->nSum
+=
(pRoot->R
-pRoot->L
+
1)
*
pRoot->Inc
;Add(
pRoot->pLeft,pRoot->L,Mid(pRoot),pRoot->Inc);Add(
pRoot->pRight,Mid(pRoot)
+
1,pRoot->R,pRoot->Inc);pRoot->Inc
=
0;if(
b
<=
Mid(pRoot))return
QuerynSum(pRoot->pLeft,a,b);else
if(
a
>=
Mid(pRoot)
+
1)return
QuerynSum(pRoot->pRight,a,b);else
{return
QuerynSum(pRoot->pLeft,a,Mid(pRoot))
+QuerynSum(pRoot->pRight,Mid(pRoot)
+
1,b);}}int
main(){int
n,q,a,b,c;char
cmd[10];scanf("%d%d",&n,&q);int
i,j,k;nCount
=
0;BuildTree(Tree,1,n);for(
i
=
1;i<=
n;i++
)
{scanf("%d",&a);Insert(Tree,i,a);}for(
i
=
0;i<
q;i
++
)
{scanf("%s",cmd);if
(
cmd[0]
==
'C'
)
{scanf("%d%d%d",&a,&b,&c);Add(
Tree,a,b,c);}else
{scanf("%d%d",&a,&b);printf("%I64d\n",QuerynSum(Tree,a,b));}}return0;}離散化有時(shí),區(qū)間的端點(diǎn)不是整數(shù),或者區(qū)間太大導(dǎo)致建樹(shù)內(nèi)存開(kāi)銷(xiāo)過(guò)大MLE
,那么就需要進(jìn)行“離散化”后再建樹(shù)。POJ
2528
Mayor's
posters給定一些海報(bào),可能互相,告訴你每個(gè)海報(bào)寬度(高度都一樣)和先后疊放次序,問(wèn)沒(méi)有被完全蓋住的海報(bào)有多少?gòu)垺:?bào)最多10,000張,但是墻有10,000,000塊瓷磚長(zhǎng)。海報(bào)端點(diǎn)不會(huì)落在瓷磚中間。POJ
2528
Mayor's
posters如果每個(gè)葉子節(jié)點(diǎn)都代表一塊瓷磚,那么線段樹(shù)會(huì)導(dǎo)致MLE,即單位區(qū)間的數(shù)目太多。實(shí)際上,由于最多10,000個(gè)海報(bào),共計(jì)20,000個(gè)端點(diǎn),這些端點(diǎn)把墻最多分成19,999個(gè)單位區(qū)間(題意為整個(gè)墻都會(huì)被蓋到)只要對(duì)這19,999個(gè)區(qū)間
,然后建樹(shù)即可。這就是離散化。POJ
2528
Mayor's
posters.這些單位區(qū)間
段樹(shù)上是葉子節(jié)點(diǎn).每個(gè)單位區(qū)間要么全被覆蓋,要么全部露出.沒(méi)有海報(bào)的端點(diǎn)會(huì)落在一個(gè)單位區(qū)間.每張海報(bào)一定完整覆蓋若干個(gè)連續(xù)的單位區(qū)間.要算出一共有多少個(gè)單位區(qū)間,并且算出每張海報(bào)覆蓋的單位區(qū)間[a,b](海報(bào)覆蓋了從a號(hào)單位區(qū)間到b號(hào)單位區(qū)間)按上圖的離散化方法,求每張海報(bào)覆蓋了哪些單位區(qū)間比較慢nlog(n),或比較難想更好的離散化方法,是將所有海報(bào)的端點(diǎn)瓷磚排序,把每個(gè)海報(bào)的端點(diǎn)瓷磚都看做一個(gè)單位區(qū)間,兩個(gè)相鄰的端點(diǎn)瓷磚之間的部分是一個(gè)單位區(qū)間這樣最多會(huì)有20000+19999個(gè)單位區(qū)間數(shù)據(jù)的順序
------
從上往下依關(guān)鍵:次每張海報(bào),這樣后能覆蓋先 的海報(bào),因此的海報(bào)不可一張海報(bào)時(shí),如果發(fā)現(xiàn)海報(bào)對(duì)應(yīng)區(qū)間有一部分露出來(lái),就說(shuō)明該海報(bào)部分可見(jiàn)。POJ
2528
Mayor's
posters如果海報(bào)端點(diǎn)坐標(biāo)是浮點(diǎn)數(shù),其實(shí)也一樣處理。樹(shù)節(jié)點(diǎn)要保存哪些信息,而且這些信息該如何動(dòng)態(tài)更新呢?POJ
2528
Mayor's
postersstruct
CNode{int
L,R;bool
bCovered;CNode
*
pLeft,
*
pRight;};bCovered表示本區(qū)間是否已經(jīng)完全被海報(bào)蓋住#include
<iostream>#include
<algorithm>#include
<math.h>using
namespace
std;int
n;struct
CPost{int
L,R;};CPost
posters[10100];int
x[20200];int
hash[10000010];//hash[i]表示瓷磚i所處的離散化后的區(qū)間
struct
CNode{int
L,R;bool
bCovered;//區(qū)間[L,R]是否已經(jīng)被完
CNode
*
pLeft,*
pRight;};CNode
Tree[1000000];int
nNodeCount
=
0;int
Mid(
CNode
*
pRoot){return
(pRoot->L
+
pRoot->R)/2;}void
BuildTree(
CNode
*
pRoot,
int
L,
int
R){pRoot->L
=L;pRoot->R=
R;pRoot->bCovered
=
false;if(
L
==
R
)return;nNodeCount
++;pRoot->pLeft
=
Tree
+
nNodeCount;nNodeCount
++;pRoot->pRight
=
Tree
+
nNodeCount;BuildTree(
pRoot->pLeft,L,(L+R)/2);BuildTree(
pRoot->pRight,(L+R)/2
+
1,R);}bool
Post(
CNode *pRoot,
int
L,
int
R){//
一張正好覆蓋區(qū)間[L,R]的海報(bào),返回true則說(shuō)明區(qū)間[L,R]是部分或全部可見(jiàn)的if(
pRoot->bCovered
) return
false;if(
pRoot->L
==
L
&&
pRoot->R
==
R){pRoot->bCovered
=
true;return
true;}bool
bResult
;if(
R
<=
Mid(pRoot)
)bResult
=
Post(
pRoot->pLeft,L,R);else
if(
L
>=
Mid(pRoot)
+
1)bResult
=
Post(
pRoot->pRight,L,R);else
{bool
b1
=
Post(pRoot->pLeft
,L,Mid(pRoot));bool
b2
=
Post(
pRoot->pRight,Mid(pRoot)
+
1,R);bResult
=
b1
||
b2;}//要更新根節(jié)點(diǎn)的覆蓋情況if(
pRoot->pLeft->bCovered
&&pRoot->pRight->bCovered
)pRoot->bCovered
=
true;return
bResult;}int
main(){int
t;
int
i,j,k;scanf("%d",&t);int
nCaseNo
=
0;while(t--)
{nCaseNo
++;scanf("%d",&n);int
nCount
=
0;for(
i
=
0;i
<
n;i
++
)
{scanf("%d%d",
&
posters[i].L,&
posters[i].R
);x[nCount++]
=
posters[i].L;x[nCount++]
=
posters[i].R;}sort(x,x+nCount);nCount=unique(x,x+nCount)-x;//去掉重復(fù)元素//下面離散化int
nIntervalNo=
0;for(
i
=
0;i
<
nCount;i
++
)
{hash[x[i]]
=
nIntervalNo;if(
i
<
nCount
-
1)
{if(
x[i+1]
-
x[i]
==1)nIntervalNo
++;elsenIntervalNo
+=
2;}}BuildTree(
Tree,0,nIntervalNo
);int
nSum
=
0;for(
i=n-1;i>=0;i--){//從后往前看每個(gè)板是否可見(jiàn)if(
Post(Tree,hash[posters[i].L],hash[posters[i].R]))nSum
++;}printf("%d\n",nSum);}return
0;}POJ
1151
Atlantis給定一些矩形,其頂點(diǎn)坐標(biāo)是浮點(diǎn)數(shù),可能互相,問(wèn)這些矩形覆蓋到的面積是多大。用線段樹(shù)做,先要離散化??!POJ
1151
Atlantis在Y軸進(jìn)行離散化。n個(gè)矩形的2n個(gè)橫邊縱坐標(biāo)共構(gòu)成最多2n-1個(gè)區(qū)間的邊界,對(duì)這些區(qū)間
,建立起線段樹(shù)。POJ
1151
Atlantis線段樹(shù)的節(jié)點(diǎn)要保存哪些信息?如何將一個(gè)個(gè)矩形線段樹(shù)?過(guò)程中這些信息如何更新?怎樣查詢?POJ
1151
Atlantisstruct
CNode{int
L,R;CNode
*
pLeft,
*
pRight;double
Len;//當(dāng)前,本區(qū)間上有多長(zhǎng)的部分是落在那些矩形中的int
Covers;//本區(qū)間當(dāng)前被多少個(gè)矩形完全包含};一開(kāi)始,所有區(qū)間
Len
=
0 Covers
=
0POJ
1151
Atlantis數(shù)據(jù)的順序:將矩形的縱邊從左到右排序,然后依次將這些縱邊線段樹(shù)。要記住哪些縱邊是一個(gè)矩形的左邊(開(kāi)始邊),哪些縱邊是一個(gè)矩形的右邊(結(jié)束邊),時(shí),對(duì)Len和Covers做不同的修改。一條邊后,就根據(jù)根節(jié)點(diǎn)的Len
值增加總覆蓋面積的值。增量是Len
*
本邊到下一條邊的距離#include
<iostream>#include
<algorithm>#include
<math.h>#include
<set>using
namespace
std;double
y[210];struct
CNode{int
L,R;CNode
*
pLeft,
*
pRight;double
Len;//當(dāng)前,本區(qū)間上有多長(zhǎng)的部分是落在那些矩形中的int
Covers;//本區(qū)間當(dāng)前被多少個(gè)矩形完全包含};CNode
Tree[1000];struct
CLine{double
x,y1,y2;bool
bLeft;//是否是矩形的左邊}
lines[210];int
nNodeCount
=
0;bool
operator<
(
const
CLine
&
l1,const
CLine
&
l2){return
l1.x
<
l2.x;}template
<class
F,class
T>
F
bin_search(F
s,
F
e,
T
val){F
L
=
s;F
R
=
e
-
1;while(L
<=
R
)
{F
mid=
L
+
(R-L)/2;if(
!(
*
mid
<
val ||
val
<
*
mid
))return
mid;else
if(val
<
*
mid)R
=
mid
-
1;elseL
=
mid
+
1;}returne;}int
Mid(CNode
*
pRoot){return
(pRoot->L
+
pRoot->R
)>>1;}void
Insert(CNode
*
pRoot,int
L,
int
R)矩形左邊的一部分或全部,該左邊的一部分或全//在區(qū)間pRoot部覆蓋了區(qū)間[L,R]{if(
pRoot->L
==
L
&&
pRoot->R
==R){pRoot->Len
=
y[R+1]
-
y[L];pRoot->Covers
++;return;}if(
R
<=
Mid(pRoot))Insert(pRoot->pLeft,L,R);else
if(
L
>=
Mid(pRoot)+1)Insert(pRoot->pRight,L,R);else
{Insert(pRoot->pLeft,L,Mid(pRoot));Insert(pRoot->pRight,Mid(pRoot)+1,R);}if(
pRoot->Covers==0)
//如果不為0,則說(shuō)明本區(qū)間當(dāng)前仍然被某個(gè)矩形完全包含,則不能更新LenpRoot->Len
=
pRoot->pLeft
->Len
+pRoot->pRight
->Len;}void
Delete(CNode
*
pRoot,int
L,
int
R)
{/在區(qū)間pRoot
刪除矩形右邊的一部分或全部,該矩形右邊的一部分或全部覆蓋了區(qū)間[L,R]if(
pRoot->L
==
L
&&
pRoot->R
==
R)
{pRoot->Covers
--;if(
pRoot->Covers
==
0
)if(
pRoot->L
==
pRoot->R
)pRoot->Len
=
0;elsepRoot->Len
=
pRoot->pLeft
->Len
+pRoot->pRight
->Len;return
;}if(
R
<=
Mid(pRoot))Delete(pRoot->pLeft,L,R);else
if(
L
>=
Mid(pRoot)+1)Delete(pRoot->pRight,L,R);else
{Delete(pRoot->pLeft,L,Mid(pRoot));Delete(pRoot->pRight,Mid(pRoot)+1,R);}if(pRoot->Covers==0)//如果不為0,則說(shuō)明本區(qū)間當(dāng)前仍然被某個(gè)矩形完全包含,則不能更新LenpRoot->Len
=
pRoot->pLeft
->Len
+
pRoot->pRight
->Len;}void
BuildTree(
CNode
*
pRoot,
int
L,int
R){pRoot->L
=L;pRoot->R=
R;pRoot->Covers
=
0;pRoot->Len=
0;if(
L
==
R)return;nNodeCount
++;pRoot->pLeft
=
Tree
+
nNodeCount;nNodeCount
++;pRoot->pRight
=
Tree
+
nNodeCount;BuildTree(
pRoot->pLeft,L,(L+R)/2);BuildTree(
pRoot->pRight,(L+R)/2+1,R);}int
main(){int
n;int
i,j,k; double
x1,y1,x2,y2; int
yc,lc;int
nCount
=
0;int
t
=
0;while(true)
{scanf("%d",&n);if(
n
==
0)
break;t
++; yc
=
lc
=
0;for(
i
=
0;i
<
n;i
++
)
{scanf("%lf%lf%lf%lf",&x1,
&y1,&x2,&y2);y[yc++]
=y2;lines[lc].y1
=
y1;y[yc++]
=y1;lines[lc].x
=
x1;lines[lc].y2
=
y2;lines[lc].bLeft
=
true;lc
++;lines[lc].x
=
x2;
lines[lc].y1
=
y1;lines[lc].y2
=
y2;lines[lc].bLeft
=
false;lc
++;}sort(y,y
+
yc);yc
=
unique(y,y+yc)
-
y;nNodeCount
=
0;//yc是橫線的條數(shù),yc-1是縱向區(qū)間的個(gè)數(shù),這些區(qū)間從0//開(kāi)始
,那么最后一個(gè)區(qū)間//
就是yc-1-1BuildTree(Tree,
0,
yc
-
1
-
1);sort(lines,lines
+
lc);double
Area
=
0;for(
i
=
0;i
<
lc
-
1
;
i
++
)
{int
L
=
bin_search(
y,y+yc,lines[i].y1)
-
y;int
R=
bin_search(
y,y+yc,lines[i].y2)
-y;if(
lines[i].bLeft
)Insert(Tree,L,R-1);elseDelete(Tree,L,R-1);Area
+=
Tree[0].Len
*
(lines[i+1].x
-
lines[i].x);}printf("Test
case
#%d\n",t);printf("Total
explored
area:%.2lf\n",Area);printf("\n",Area);}return0;}有時(shí),不一定能夠一眼看出
“區(qū)間”,這就要靠仔細(xì)觀察,造出“區(qū)間”來(lái)。例如:POJ
3321
Apple
Tree每個(gè)分叉點(diǎn)及末梢可能有蘋(píng)果(最多1個(gè)),每次可以摘掉一個(gè)蘋(píng)果,或有一個(gè)蘋(píng)果新長(zhǎng)出來(lái),隨時(shí)查詢某個(gè)分叉點(diǎn)往上的子樹(shù)里,一共有多少個(gè)蘋(píng)果。POJ
3321
Apple
Tree深度優(yōu)先遍歷整個(gè)蘋(píng)果樹(shù),為每個(gè)節(jié)點(diǎn)標(biāo)記一個(gè)開(kāi)始時(shí)間和結(jié)束時(shí)間(所有時(shí)間都不相同),顯然子樹(shù)里面所有節(jié)點(diǎn)的開(kāi)始和結(jié)束時(shí)間,都位于子樹(shù)樹(shù)根的開(kāi)始和結(jié)束時(shí)間之間。問(wèn)題變成:有n個(gè)節(jié)點(diǎn),就有2n個(gè)開(kāi)始結(jié)束時(shí)間,它們構(gòu)成序列A1A2….A2n序列里每個(gè)數(shù)是0或者1,可變化,隨時(shí)查詢某個(gè)區(qū)間里數(shù)的和。當(dāng)然由于蘋(píng)果樹(shù)上每個(gè)放蘋(píng)果的位置對(duì)應(yīng)于數(shù)列里的兩個(gè)數(shù),所以結(jié)果要除以2樹(shù)狀數(shù)組對(duì)于序列a,
設(shè)一個(gè)數(shù)組CC[i]
=
a[i
–
2k
+
1]
+
…
+
a[i]k為i在二進(jìn)制下末尾0的個(gè)數(shù)2k就是i
保留最右邊的1,其余位全變0i從1開(kāi)始算!C即為a的樹(shù)狀數(shù)組對(duì)于i,如何求2k
?2k=i
&(i^(i-1))也就是i&(-i)以6為例(6)10=(0110)2xorand通常6-1=(5)10=(0101)2(0011)2(6)10=
(0110)2(0010)2
=
(4)10用lowbit(x)表示x對(duì)應(yīng)的2k
,lowbit(x)
=
x&(-x)lowbit(x)
實(shí)際上就是x的二進(jìn)制表示形式留下最右邊的1,其他位都變成0C[i]=a[i-lowbit(i)+1]+…+a[i]C包含哪些項(xiàng)看上去沒(méi)有規(guī)律C1=A1C2=A1+A2C3=A3C4=A1+A2+A3+A4C5=A5C6=A5+A6C7=A7C8=A1+A2+A3+A4+A5+A6+A7+A8…………C16=A1+A2+A3+A4+A5+A6+A7+A8+A9+A10+A11+A12+A13+A14+A15+A16樹(shù)狀數(shù)組圖示樹(shù)狀數(shù)組的好處在于能快速求任意區(qū)間的和a[i]
+
a[i+1]
+
…
+
a[j]設(shè)sum(k)=a[1]+a[2]+…+a[k]則a[i]+a[i+1]+…+a[j]=sum(j)-sum(i-1)有了樹(shù)狀數(shù)組,sum(k)就能在O(logN)時(shí)間內(nèi)求出,N是a數(shù)組元素個(gè)數(shù)。而且更新一個(gè)a的元素所花的時(shí)間也是O(logN)的(a更新了C也得更新)。為什么呢?根據(jù)C的構(gòu)成規(guī)律,可以發(fā)現(xiàn)sum(k)可以表示為:sum(k)
=
C[n1]+C[n2]
+
…+
C[nm]其中nm=kni-1=ni
-lowbit(ni)而且n1
–lowbit(n1
)必須小于或等于0(其實(shí)只能等于0),n1大于0如:sum(6)=C[4]+C[6]lowbit(x)
實(shí)際上就是x的二進(jìn)制表示形式留下最右邊的1,其他位都變成0那么,sum(k)最多有幾項(xiàng)呢?這個(gè)決定了求區(qū)間和的時(shí)間復(fù)雜度那么,sum(k)最多有幾項(xiàng)呢?sum(k)=C[n1]+C[n2]+…+C[nm]其中nm=kni-1
=
ni
-
lowbit(ni)lowbit(x)
實(shí)際上就是x的二進(jìn)制表示形式留下最右邊的1,其他位都變成0ni
-lowbit(ni)是什么樣子?就是ni的二進(jìn)制去掉最右邊的1k
的二進(jìn)制里最多有幾個(gè)1?log2
k
(向上取整)個(gè)sum(k)最多l(xiāng)og2
k(向上取整)項(xiàng),所以本次求和的復(fù)雜度就是log2
k那么,為什么sum(k)
=
C[n1]+C[n2]
+
…+
C[nm]其中nm=kni-1
=
ni
-
lowbit(ni)證:C[i]
=
a[i-lowbit(i)+1]
+
…+
a[i]i-lowbit(i)+1
是什么?就是i把最右邊的1去掉,然后再加1那么,為什么sum(k)=a[1]+a[2]+…+a[k]=C[n1]+C[n2]+…+C[nm](其中nm=k)證明:C[nm]
=
a[nm-lowbit(nm)+1]
+
…
+
a[nm]C[nm-1]
=
a[nm-1-lowbit(nm-1)+1]
+
…
+a[nm-1]=
a[nm-1-lowbit(nm-1)+1]
+
…
+
a[nm-lowbit(nm)]C[nm-2]
=
a[nm-2-lowbit(nm-2)+1]
+
…
+
a[nm-2]=
a[nm-1-lowbit(nm-1)+1]
+
…
+
a[nm-1-lowbit(nm-1)]……..C[n1]
=
a[n1-lowbit(n1)+1]
+
…+
a[n1]=
a[1]
+
…+
a[n1](因n1-lowbit(n1)必須等于0,否則就還需要C[n1-lowbit(n1)]了)更新一個(gè)a元素,C也要跟著更新,復(fù)雜度是多少呢即C里有幾項(xiàng)要更新呢?C1=A1C2=A1+A2C3=A3C4=A1+A2+A3+A4C5=A5C6=A5+A6C7=A7C8=A1+A2+A3+A4+A5+A6+A7+A8…………C16=A1+A2+A3+A4+A5+A6+A7+A8+A9+A10+A11+A12+A13+A14+A15+A16更新一個(gè)a元素,C也要跟著更新,復(fù)雜度是多少呢即C里有幾項(xiàng)要更新呢?如果a[i]更新了,那么以下的幾項(xiàng)都需要更新:C[n1],
C[n2],
…C[nm]其中,n1
=i
,ni+1=ni
+lowbit(ni)nm
+lowbit(nm)必須大于a
的元素個(gè)數(shù)N,
nm小于等于N同理,總的來(lái)說(shuō)更新一個(gè)元素的時(shí)間,也是logN的為什么如果a[i]更新了,那么有且僅有以下的幾項(xiàng)需要更新:C[n1],
C[n2],
…C[nm]其中,n1
=i
,ni+1=ni
+lowbit(ni)a[i]更新->C[i]必須更新C[i]更新->C[i+lowbit(i)]必須更新:C[i+lowbit(i)]
=
a[
(i+lowbit(i))
–
lowbit(i+lowbit(i))
+1]
+….
+a[i+lowbit(i)]證明i+lowbit(i)–lowbit(i+lowbit(i))+1<=i,就證明
C[i+lowbit(i)]要更新lowbit(i)顯然比lowbit(i+lowbit(i))要小所以i+lowbit(i)–lowbit(i+lowbit(i))+1<=i下面要證明,若C[i]更新,則對(duì)任何k,(i<k<i+lowbit(i)),C[k]都不需要更新(
C[k]不包含a[i])C[k]
=
a[k-lowbit(k)+1]
+
…
+
a[k]只要證明k-lowbit(k)+1比i大即可因
i<k
<i+lowbit(i)
,假設(shè)i的最右邊的1是從右到左從0開(kāi)始數(shù)的第n位,那么i+lowbit(i)就是將i的低n位全變成1后,再加1。那么k一定是從第n位到最
都和i相同,但是低n位比i大(即k低n位中有1,因i低n位全是0)k-lowbit(k)+1就是k去掉最右邊的1,然后再加1,那當(dāng)然還是比i大初始狀態(tài)下由a構(gòu)建樹(shù)狀數(shù)組C的時(shí)間復(fù)雜度是多少?顯然是O(N)的因?yàn)镃[k]
=
sum(k)
–
sum(k-lowbit(k))證:sum(k)
=
C[n1]+C[n2]
+
…+
C[nm-1]
+C[nm]
(nm
=
k)nm-1
=
k-lowbit(k)sum(k-lowbit(k))
=
C[n1]+C[n2]
+
…+
C[nm-1]所以,樹(shù)狀數(shù)組適合單個(gè)元素經(jīng)常修改而且還反復(fù)要求部分的區(qū)間的和的情況。上述問(wèn)題雖然也可以用線段樹(shù)解決,但是用樹(shù)狀數(shù)組來(lái)做,編程效率和程序運(yùn)行效率都更高(時(shí)間復(fù)雜度相同,但是樹(shù)狀數(shù)組常數(shù)小)如果每次要修改的不是單個(gè)元素,而是一個(gè)
區(qū)間,那就不能用樹(shù)狀數(shù)組了(效率過(guò)低)。POJ
3321
Apple
Tree每個(gè)分叉點(diǎn)及末梢可能有蘋(píng)果(最多1個(gè)),每次可以摘掉一個(gè)蘋(píng)果,或有一個(gè)蘋(píng)果新長(zhǎng)出來(lái),隨時(shí)查詢某個(gè)分叉點(diǎn)往上的子樹(shù)里,一共有多少個(gè)蘋(píng)果。此題可用樹(shù)狀數(shù)組來(lái)做Sample
Input31
21
33Q
1C
2Q1Sample
Output32根據(jù)題意,一開(kāi)始時(shí),所有能長(zhǎng)蘋(píng)果的地方都有蘋(píng)果//樹(shù)狀數(shù)組做/*一棵樹(shù)上長(zhǎng)了蘋(píng)果,每一個(gè)樹(shù)枝節(jié)點(diǎn)上有長(zhǎng)蘋(píng)果和不長(zhǎng)蘋(píng)果
兩種狀態(tài),兩種操作,一種操作能夠改變樹(shù)枝上蘋(píng)果的狀態(tài),另一種操作詢問(wèn)某一樹(shù)枝節(jié)點(diǎn)一下的所有的蘋(píng)果有多少。具體做法是做一次dfs,記下每個(gè)節(jié)點(diǎn)的開(kāi)始時(shí)間Start[i]和結(jié)束時(shí)間End[i],那么對(duì)于i節(jié)點(diǎn)的所有子孫的開(kāi)始時(shí)間和結(jié)束時(shí)間都應(yīng)位于Start[i]和End[i]之間,另外用一個(gè)數(shù)組C[i]記錄附加在節(jié)點(diǎn)i上的蘋(píng)果的個(gè)數(shù),然后用樹(shù)狀數(shù)組統(tǒng)計(jì)Start[i]到End[i]之間的附加蘋(píng)果總數(shù)。這里用樹(shù)狀數(shù)組統(tǒng)計(jì)區(qū)間可以用Sum(Start[i])-Sum(End[i]-1)來(lái)計(jì)算。*/#include
<iostream>#include
<vector>using
namespace
std;#define
MY_MAX
220000int
C[MY_MAX];typedef
vector<int>
VCT_INT;vector<VCT_INT>
G(MY_MAX/2);int
Lowbit[MY_MAX];bool
HasApple[MY_MAX/2];int
Start[MY_MAX];//dfs時(shí)的開(kāi)始時(shí)間
int
End[MY_MAX];//dfs時(shí)的結(jié)束時(shí)間
int
nCount=0;void
Dfs(int
v){Start[v]
=
++
nCount;for(
int
i
=
0;i
<
G[v].size();i
++
)Dfs(G[v][i]);End[v]
=
++
nCount;}int
QuerySum(int
p){int
nSum
=0;while(
p
>
0
)
{nSum
+=
C[p];p-=
Lowbit[p];}return
nSum;}void
Modify(
int
p,int
val){while(
p
<=
nCount)
{C[p]
+=
val;p
+=
Lowbit[p];}}int
main(){int
n;scanf("%d",&n);int
x,y;int
i,j,k;//建圖for(
i
=
0;i
<
n
-1
;i
++
)
{int
a,b;scanf("%d%d",&a,&b);G[a].push_back(b);}nCount
=
0;Dfs(1);//樹(shù)狀數(shù)組要處理的原始數(shù)組下標(biāo)范圍1--
nCountfor(
i
=
1;i
<=
nCount;i
++)
{Lowbit[i]
=
i
&
(
i
^(
i
-
1));}for(
i
=
1;i
<=
n;i
++
)HasApple[i]
=
1;intm;//求C數(shù)組,即樹(shù)狀數(shù)組的節(jié)點(diǎn)的值
for(
i=1;i<=nCount;i++)C[i]
=
i
-
(i
-
Lowbit[i]
+
1)
+
1;scanf("%d",&m);for(
i
=
0;i
<
m;i
++
)
{char
cmd[10];inta;scanf("%s%d",cmd,&a);if(
cmd[0]
==
'C'
)
{if(
HasApple[a]
)
{Modify(
Start[a],-1); Modify(
End[a],-1);HasApple[a]
=
0;}else
{Modify(
Start[a],1);
Modify(End[a],1);HasApple[a]
=
1;}}else
{int
t1
=
QuerySum(End[a]);int
t2
=QuerySum(Start[a]);printf("%d\n",(QuerySum(End[a])
–QuerySum(Start[a]))/2
+
HasApple[a]);}}}二維樹(shù)狀數(shù)組原始數(shù)組和樹(shù)狀數(shù)組都是二維的C[x][y]
=
∑
{a[i][j]}x-lowbit[x]+1
<=
i
<=xy-lowbit[y]+1
<=
j
<=ySum[x][y]=∑{C[i][j]} (從[1,1]
到[x,y]這個(gè)矩陣?yán)锏乃性氐暮停﹊1=x,
i2
=i1-lowbit(i1),
…ik
=
ik-1-lowbit(ik-1)
…..j1=y,
j2
=
j1-lowbit(j1),
…jk
=
jk-1-lowbit(jk-1)
…..用于快速求數(shù)字子矩陣的和,更新和查詢的時(shí)間復(fù)雜度都是log(n)*log(m)(n,m分別為兩維的大小)POJ
1195
Mobile
phones一個(gè)由數(shù)字構(gòu)成的大矩陣,開(kāi)始是全0,能進(jìn)行兩種操作對(duì)矩陣?yán)锏哪硞€(gè)數(shù)加上一個(gè)整數(shù)(可正可負(fù))查詢某個(gè)子矩陣?yán)锼袛?shù)字的和要求對(duì)每次查詢,輸出結(jié)果Sample
Input0
41
1
2
32
0
0
2
21
1
1
21
1
2
-12
1
1
2
33Sample
Output34//下面為二維樹(shù)狀數(shù)組解法
#include<iostream>#include<vector>using
namespace
std;#define
MY_MAX
1100int
C[MY_MAX][MY_MAX];int
Lowbit[MY_MAX];int
s;void
Add(
int
y,
int
x,int
a){while(
y
<=
s
)
{int
tmpx
=
x;while(
tmpx
<=
s
)
{C[y][tmpx]
+=
a;tmpx
+=
Lowbit[tmpx];}y
+=
Lowbit[y];}}int
QuerySum(
int
y,
int
x)//查詢第1行到第y行,第1列到第x列的和{int
nSum
=0;while(y
>
0
)
{int
tmpx
=x;while(
tmpx
>
0)
{nSum
+=
C[y][tmpx];tmpx
-=
Lowbit[tmpx];}y
-=Lowbit[y];}return
nSum;}int
main()
{intcmd; int
x,y,a,l,b,r,t; int
i,j,k; int
n1,n2;for(
i
=
1;i
<=
MY_MAX;i
++
)
Lowbit[i]
=
i
&
(
i
^(i
-
1));while(
true)
{scanf("%d",&cmd);switch(
cmd)
{case
0:scanf("%d",&s);memset(C,0,sizeof(C));break;case
1:scanf("%d%d%d",&x
,&y,&a);Add(
y
+
1,x
+1,
a);break;case2:scanf("%d%d%d%d",&l
,
&b,
&r,&t);int
n1,n2,n3,n4;l
++;
b++;
r
++;
t++;printf("%d\n",QuerySum(t,r)
+QuerySum(b-1,l-1)
-
QuerySum(t,l-1)
-
QuerySum(b-1,r));break;case
3: return0;}}}二維線段樹(shù)一維線段樹(shù)的每個(gè)節(jié)點(diǎn)代表一個(gè)一維區(qū)間,那么二維線段樹(shù)的每個(gè)節(jié)點(diǎn)就代表一個(gè)二維區(qū)間(一個(gè)矩陣)二維線段樹(shù)是一棵4叉樹(shù)。如果一個(gè)節(jié)點(diǎn)代表的區(qū)間是矩陣[x1,y1]–[x2,y2],那么它的四個(gè)子節(jié)點(diǎn)代表的區(qū)間分別為[x1,y1]
–
[(x1+x2)/2,
(y1+y2)/2][x1,(y1+y2)/2+1]
–
[(x1+x2)/2,y2][
(x1+x2)/2+1,y1]
–
[x2,
(y1+y2)/2][(x1+x2)/2+1,
(y1+y2)/2+1]
–
[x2,y2]二維線段樹(shù)二維線段樹(shù)的四叉樹(shù)實(shí)現(xiàn)形式,請(qǐng)參考:http
/menjitianya/archive/2011/04/03/143374.html二維線段樹(shù)還可以用樹(shù)套樹(shù)方式實(shí)現(xiàn),即每個(gè)外層線段樹(shù)的節(jié)點(diǎn)對(duì)應(yīng)于一棵內(nèi)層線段樹(shù)。如果外層線段樹(shù)根對(duì)應(yīng)的區(qū)間是x方向的[1,n],內(nèi)層線段樹(shù)根節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間是y方向的[1,m],那么整個(gè)線段樹(shù)可以存在一個(gè)n行m列的二維數(shù)組里。樹(shù)套樹(shù)方式
、修改、查找等時(shí)間復(fù)雜度為O(log(n)*log(m))。用二維線段樹(shù)做POJ
1195
Mobile
phones#include
<iostream>using
namespace
std;#d
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 生態(tài)補(bǔ)償款禁養(yǎng)協(xié)議書(shū)(2篇)
- 環(huán)境監(jiān)測(cè)設(shè)備研發(fā)合同(2篇)
- 七年級(jí)數(shù)學(xué)下冊(cè)14.1用有序數(shù)對(duì)表示位置聽(tīng)評(píng)課記錄
- 粵人版地理七年級(jí)下冊(cè)《第一節(jié) 美洲概述》聽(tīng)課評(píng)課記錄5
- 湘教版數(shù)學(xué)九年級(jí)下冊(cè)1.2《二次函數(shù)的圖象與性質(zhì)》聽(tīng)評(píng)課記錄1
- 華師大版歷史九年級(jí)上冊(cè)第1課《古代埃及》聽(tīng)課評(píng)課記錄1
- 北師大版道德與法治九年級(jí)上冊(cè)9.1《培育社會(huì)主義核心價(jià)值觀》聽(tīng)課評(píng)課記錄
- 部編人教版歷史九年級(jí)上冊(cè)第11課《古代日本》聽(tīng)課評(píng)課記錄
- 八年級(jí)道德與法治下冊(cè)第一單元堅(jiān)持憲法至上第二課保障憲法實(shí)施第2框加強(qiáng)憲法監(jiān)督聽(tīng)課評(píng)課記錄(新人教版)
- 五年級(jí)上冊(cè)數(shù)學(xué)聽(tīng)評(píng)課記錄《5.3 分餅》(1)-北師大版
- 環(huán)衛(wèi)一體化運(yùn)營(yíng)方案
- 《基于PPT課件的高中英語(yǔ)閱讀策略探究》
- DTⅡ型固定式帶式輸送機(jī)(托輥)
- 工程項(xiàng)目居間合同協(xié)議書(shū)居間合同協(xié)議書(shū)
- 普通話測(cè)試培訓(xùn)課件2:讀單音節(jié)字詞
- 電梯維保競(jìng)爭(zhēng)性磋商文件
- 科技進(jìn)步類(lèi)現(xiàn)代軌道交通綜合體設(shè)計(jì)理論與關(guān)鍵技術(shù)公
- 不同課型的課堂教學(xué)基本范式
- 損失物品清單
- 熱控專(zhuān)業(yè)工程質(zhì)量驗(yàn)收及評(píng)定范圍劃分表
- 跨河管道桁架施工方案完整
評(píng)論
0/150
提交評(píng)論