Cây quản lý phạm vi
này gii thiu cây qun lý phm vi (range trees). t cu trúc d
liu quan trng, có nhiu ng dng trong các thut toán hình hc, truy v d
liu và x lý tín hiu. Cây qun lý ph cp nhiu trong các k thi
olympic tin hc trong kho l
1. Giới thiệu
Gi s ta có m d liu cha h a các nhân viên trong mt
công ty, thông tin v mi nhân viên là mt bn ghi gm nhia
chp b d liu này luôn bing bi các
lnh thêm/bt/cp nht b i truy vn d m s
i tui t 40 ti 50 và có m tháng t 3 triu ti 5
triu Tính ta nhi có thâm niên công tác t 10
lên và có t 2 ti 4 con
Dng bài toán qung và tr li các dng truy vn k trên có th mô
i dng hình hc: Chng hn ta có th biu din mi nhân viên bi
mm trên mt phng t vi trc t là tui và trc t
là mm s tui t 40 ti
50 và có m 3 ti 5 tri din gii thành: m s m
có t
(Xem Hình 1)
Hình 1
Bài toán truy vn phm vi có th phát biu hình thn qun lý
mt tp các ng biu din bi các m trong không gian chiu, mi
m ngoài t ca nó còn có th cha thêm mt s thông tin khác
*
. Tp
liên tc bing bi phép thêm/bi các truy vn. Mi truy
vn, cho bi phm vi là mt siêu hp
,
yêu cu tr li v thông tin tng hp t tt c m nm trong siêu hp .
này, ta quan tâm ti các dng thông tin tng hp có tính cht
trc là nu và là hai tm ri nhau thì thông tin tng hp
t m có th d c t thông tin tng hp trên và
thông tin tng hp trên v d liu nhân s, ta có th d
c:
S i trong tp bng cách ly s i trong cng s i
trong .
a nt trong tp ,
có th
nh bng công thc
S u tp ch g lc tt c
nhm nm trong phm vi truy vn và tng hp thông tin t nhm
m ln, mc dù phép thêm bm có th thc hin
*
Trong CSDL quan h, mt s ct s nh làm t và nhng ct còn li s c coi là thông tin cn
truy vn tùy theo tng ng dng c th.
Ο
40
50
3.000.000
5.000.000
nhanh (thi gian
nu s dng cu trúc d ling),
thi gian truy vn tr nên rt chm (mt
thi gian tr li mi
truy vn vi là s m trong và là s chiu ca không gian).
Cây qun lý phm vi là mt cu trúc d liu hiu qu gii quyt bài toán
trên, nó cho phép thc hin mi phép thêm, bt, cp nht, truy vn trong thi
gian
, thích hp vi x lý d liu lng
t
chm so vi ng
khi
Trong các phn tip theo, phn 2 kho sát mt s cu trúc d liu và thut
toán gii quyt bài toán truy vn phm vi 1 chiu. Phn 3 m rng các cu
trúc d liu cho truy vn phm vi nhiu chiu. Phn 4 là mt s bài toán ng
dng, m rng ca cây qun lý phm vi, cui cùng là kt lun và danh mc tài
liu tham kho.
2. Truy vấn phạm vi một chiều
2.1. Cây nhị phân tìm kiếm
t nh biu din danh sách là s dng mng
hoc danh sách móc ni. S dng mng có t tt vi phép truy cp ngu
nhiên b chm nu danh sách luôn b bi ng bi các phép
dng danh sách móc ni có th thun ti
trong các phép chèn/xóa thì li g m trong phép truy cp ngu
nhiên.
Trong mc này chúng ta s trình bày mu din danh sách
bng cây nh p ngu nhiên, chèn, xóa và truy
vn c thc hin trong thi gian
. N
c trình bày qua mt bài toán c th:
Bài toán (Range Query):
Cho mt danh sách cha các s nguyên. Ký hiu
là s phn t
trong danh sách. Các phn t liên tip bu
t 1.
Bu vi mt danh sách rng, xét các phép bii danh sách
Phép chèn
: Chèn mt s vào v trí ca danh sách. ng
hp
thì s c thêm vào cui danh sách.
Phép xóa
: Xóa phn t th trong danh sách.
Phép cp nht
: t phn t th bng .
Phép truy vn
: Tr v tng các phn t nm trong phm vi t
ti
Yêu cu: Cho dãy phép bic thc hin tun t, hãy tr li tt c các
truy vn
Input
Dòng 1 cha s
dòng tip, mi dòng cho thông tin v mt phép bii. Mi dòng bt
u bi mt ký t
Nu ký t u dòng là thì tip theo là hai s nguyên ng
vi phép chèn
(
)
Nu ký t u dòng là thì tip theo là s nguyên ng vi
phép xóa
.
Nu ký t p theo là hai s nguyên ng
vi phép cp nht
(
)
Nu ký t p theo là hai s nguyên ng
vi phép truy vn
()
Output
Tr li tt c các truy vn , vi mi truy vn in ra câu tr li trên 1 dòng
Sample Input
Sample Output
11
I 1 8 {8}
I 1 3 {3 8}
I 3 6 {3 8 6}
I 3 2 {3 8 2 6}
Q 1 3
U 3 4 {3 8 4 6}
I 2 5 {3 5 8 4 6}
D 1 {5 8 4 6}
Q 2 4
U 1 7 {7 8 4 6}
Q 1 4
13
18
25
2.1.1. Biểu diễn danh sách
Chúng ta s các phn t ca danh sách trong mt cu trúc cây nh
phân sao cho nu duyt cây theo thứ tự giữa thì các phn t ca s c lit
t trong danh sách. Cây nh t bi mt
cu trúc liên kng và con trng chính ca cách tip cn này
là đồng bộ thứ tự của danh sách trừu tượng với thứ tự giữa của cây, quy việc
chèn xóa trên về việc chèn xóa trên cây nhị phân.
Có mt s ng gia cu trúc d liu này và cây nh phân tìm
kim (binary search trees – BST):
Nu danh sách trng gm các phn t p xn thì t
nhiên cây biu din danh sách tr thành cây nh phân tìm kim.
Nu duyt cây nh phân tìm kim theo th t gin
các khóa tìm kim, còn nu duyt cây biu din danh sách theo th t
gia ta s c danh sách .
Có th có nhiu cu trúc cây nh phân tìm kim ng vi mt tp khóa tìm
ki y có nhiu cu trúc cây biu din danh sách ng vi
danh sách .
ng cây biu din danh sách có th k tha t cây
nh phân tìm kim bi các k thut cân bng cây nh phân tìm kim luôn
bo tn th t gia cng vi th t n ca các
khóa tìm king b th t danh sách vi th t
gia ca các nút trên cây ch không phi là th t c hay th t sau.
Chính vì có nhing gia cu trúc cây biu din danh sách và
cây nh phân tìm kim, tcây nh phân tìm kim binary search
trees (BST) cho cu trúc d liu này.
2.1.2. Cấu trúc nút
Có th thy rng khi duyt cây theo th t gia thì các nút mt nhánh cây s
c lit kê trong mn liên tip, không có nút nhánh khác xen vào. Nói
cách khác, bn cht mi nhánh cây là mn các phn t liên tip trong
danh sách trng . i ý cho vi thêm nhng thông tin
tng hp v n liên tip này ti nhng mng hp
c th này, mi nút s cha thêm 2 thông tin: S nút trong nhánh gc
thc hin phép truy cp ngu nhiên) và tng các phn t trong
nhánh gc tr li truy vn tng).
Tóm li, mi nút trên cây là mt bn ghi gng:
ng : Cha phn t
ng Cha liên kt (con tr) ti nút cha, nu là nút gc (không có nút
ng t bng mt con tr c bit, ký hiu .
ng : Cha liên kt (con tr) ti nút con trái, nu nút không có nhánh
con trái thì tng t bng .
ng : Cha liên kt (con tr) ti nút con phi, nu nút không có
nhánh con phng t bng .
Trng cha s nút trong nhánh gc
ng cha tng phn t cha trong nhánh gc
Hình 2. Cây biu din danh sách gm 7 phn t (1, 7, 3, 6, 5, 4, 2)
1
7
3
6
5
4
2
type
PNode = ^TNode;
//Kiểu con trỏ tới một nút
TNode = record
key: TKey;
P, L, R: PNode;
len: Integer;
sum: Int64;
end;
var
sentinel: TNode;
nilT: PNode;
//Con trỏ tới nút đặt biệt
root: PNode;
//Con trỏ tới nút gốc
begin
nilT := @sentinel;
nilT^.size := 0;
nilT^.sum := 0;
end.
Các ngôn ng lp trình bng cung cp hng con tr (hay
gán cho các liên kt không tn ti trong cu trúc d liu. Hng con tr ch
c s dng so sánh vi các con tr c phép truy cp bin
ng .
t cây nh phân, chúng ta s dng con tr gán cho nhng liên
kt không có thc (công d ). Ch có khác là con tr
tr ti mt bin có thực m ng ca là vô
nghĩa. Chúng ta hy sinh mt ô nh cho bin n hóa
các thao tác trên cây
*
.
Th tc
ng hp các thông tin trong t nhng thông tin
ph tr trong hai nút con:
procedure Update(x: PNode);
begin
x^.len := x^.L^.len + x^.R^.len + 1;
//Tính số nút trong nhánh x
x^.sum := x^.L^.sum + x^.R^.sum + x^.value;
//Tính tổng các phần tử trong nhánh x
end;
c và .
d trình bày các thao tác, ta vit sn các th tc móc ni các nút: Th tc
cho làm con trái , th tc
cho làm con phi
*
Ma bi bm tra con tr c khi truy cp nút .
procedure SetL(x, y: PNode);
begin
y^.P := x; x^.L := y;
end;
procedure SetR(x, y: PNode);
begin
y^.P := x; x^.R := y;
end;
2.1.3. Truy cập ngẫu nhiên
C các phép biu có mt tham s v trí, vy viu tiên là
phng vi v trí trong danh sách trng là nút nào
trong cây. Theo nguyên lý ca phép duyt cây theo th t gia (duyt nhánh
t nhánh phi), thu
ng vi v trí có th din t
tìm nút th trong nhánh cây gc c hnh là s th t
ca nút gc (theo th t gia):
Nu thì nút cn tìm chính là nút .
Nu thì quy v tìm nút th trong nhánh con trái ca .
Nu thì quy v tìm nút th trong nhánh con phi ca .
S c l ng vi v trí có th tính b sâu ca nút
kt qu cng thêm 1. Phép truy cp ng t bng hàm
: Nhn vào nút và mt s nguyên , tr v ng vi v
c .
function NodeAt(x: PNode; i: Integer): PNode;
var
ord: Integer;
begin
repeat
ord := x^.L^.len + 1;
//Xác định số thứ tự nút x
if ord = i then Break;
//Nút cần tìm chính là x
if i < ord then
//Quy về tìm nút thứ i trong nhánh con trái
x := x^.L
else
//Quy về tìm nút thứ i – ord trong nhánh con phải
begin
i := i - ord;
x := x^.R;
end;
until False;
Result := x;
end;
2.1.4. Vấn đề cân bằng cây
Thao tác truy cp ngu nhiên thc hin mt phép di chuyn t gc xung mt
nút mang s th t nh, nu cây nh phân suy bin, phép truy cp ngu
nhiên không khác gì phép truy cp tun t trên danh sách móc ni và tr
nên kém hiu qu. Rt may mn là ta có nhbng cây.
Nhc gi cho chiu cao cây là mng
vi là s nút trên cây, hom bo cho dãy thao tác truy cp ngu nhiên
c thc hin trong thi gian
. Nh
bc k tha t các cu trúc d liu cây nh phân tìm kim t cân
bng (self-balancing binary search trees
Treaps, cây nh phân tìm kim ng
Hu ht các k thut cân bc thc hin bi phép quay cây, có hai
loi: quay phi (right rotation) và quay trái (left rotation).
Nu là con trái ca , phép quay phi theo liên kt ct nhánh con
phi ca làm con trái ca làm con phi ca . Nút c
y lên làm gc nhánh thay cho nút Hình 3, có th thy
rng phép quay phi bo tn th t gia .
c li, nu là con phi ca , phép quay trái theo liên kt vi
ct nhánh con trái ca làm con phi ca làm con trái ca
y lên làm nút nhánh
thay cho nút Hình 3 thy rng phép quay trái
bo tn th t gia .
Hình 3. Phép quay cây
Ta vit mt thao tác
t i , và ,
phép
s quay theo liên kt y nút lên phía gc cây
sâu ca gim 1) và kéo nút xut mc làm con nút . Chú
ý là sau phép
, ta ch cn cp nht thông tin ph tr ca nút và
p nht thông tin ph tr ca nút ng ng ),
thông tin ph tr trong các núi.
Quay phi
Quay trái
procedure UpTree(x: PNode);
var
y, z: PNode;
begin
y := x^.P;
//y^ là nút cha của x^
z := y^.P;
//z^ là nút cha của y^
if x = y^.L then
//Quay phải
begin
SetL(y, x^.R);
//Chuyển nhánh con phải của x^ sang làm con trái y^
SetR(x, y);
//Cho y^ làm con phải x^
end
else
//Quay trái
begin
SetR(y, x^.L);
//Chuyển nhánh con trái của x^ sang làm con phải y^
SetL(x, y);
//Cho y^ làm con trái x^
end;
//Móc nối x^ vào làm con z^ thay cho y^
if z^.L = y then SetL(z, x) else SetR(z, x);
Update(y); Update(x)
end;
2.1.5. Cây Splay
Trong ví d c th này, cây Splay c s dng làm cu trúc d liu cây biu
din danh sácht trong nhng thú v nht v cây nh phân
tìm kim t cân bng [8]c thc hin ngay
khi có lnh truy cp nút, làm gi sâu ca nhng nút truy c ng
ng hp tn sut thc hin phép tìm kim trên mt khóa hay
mt c n so vi nhng khóa khác, cây Splay s phát huy
v mt t.
Thao tác Splay
Thao tác quan trng nht ca cây splay là thao tác
: nhn vào mt
nút y lên làm gc cây: Nu i gc cây, gi là nút cha ca
() và là nút cha ca (), s y dn lên gc cây
theo quy trình sau:
Nu là con ca nút gc (), mt phép
s c thc
hin và s tr thành gc cây. Thao tác này gi là phép zig.
Nu và cùng là con trái hoc cùng là con phi, mt phép
s
c thc hi y lên làm nút cha ca , tip theo là mt phép
y lên làm nút cha ca . Thao tác này gi là phép zig-
zig.
Nu và có mt nút là con trái và mt nút là con phi, hai phép
s c thc hi y lên làm nút cha ca c và . Thao
tác này gi là phép zig-zag.
Thao tác
cn s dng tt phép zig.
Hình 4. Phép zig-zig và zig-zag.
procedure Splay(x: PNode);
var
y, z: PNode;
begin
repeat
y := x^.P;
if y = nilT then Break;
//x là gốc thì dừng ngay
z := y^.P;
if z ≠ nilT then
//zig-zig hoặc zig-zag, cần 1 phép UpTree trước phép UpTree(x)
if (y = z^.L) = (x = y^.L) then UpTree(y)
//x và y cùng là con trái hoặc cùng là con phải
else UpTree(x);
//x và y có một nút con trái và một nút con phải
UpTree(x);
until False;
end;
Ti sao li làm phc tp hóa v khi mà ta có th thc hin liên tip mt
lot các thao tác
y lên gc cây?. Câu tr li là phép
ngoài viy lên thành gng làm gi
sâu ca các nút nt lên gcm ni bt ca
A
B
C
D
D
C
B
A
zig-zig
Bo toàn th t gia
zig-zag
Bo toàn th t gia
A
B
C
D
C
A
B
D
cây Splay: Nhng nút truy c ng xuyên s c làm gi sâu và
phân b gn phía gc.
Hình 5 là ví d v c và sau khi thc hin thao tác
. Thao tác
bao gm mt phép zig-zig, mt phép zig-zag và mt phép zig.
c khi
,
sâu 0,
sâu ca các nút
là:
Sau khi
,
sâu 0,
và
sâu 1,
và
sâu 2,
sâu 3. T sâu ca các nút
là:
Hình 5. Ví d v thao tác Splay
Tách
Phép tách (Split) nhn vào mt danh sách trng (biu din bi cây )
và mt ch s thành hai danh sách: Danh sách
(biu din bi cây
) gm phn t u ca và danh sách
(biu din bi
cây
) gm các phn t còn li trong . Thut toán tách có th din gi
sau:
Nu , ta gán
và
b ng hp này danh
sách
và
.
E
D
C
B
A
F
G
B
C
D
A
E
F
G
Nu x nh nút
cha phn t ng th bng hàm
y
lên gc cây bng lnh
nh
là nút
con phi ca
. Vì th t gic bo tn, nút
vng th
theo th t gia. Vic cui cùng ch là ct b liên kt gia
và nhánh con
phi
c to thành hai cây.
Chú ý rng sau phép tách cây thành hai cây
và
, ta ph
b hc s dng na.
procedure Split(T: PNode; i: Integer; var T1, T2: PNode);
begin
if i = 0 then
begin
T1 := nilT; T2 := T;
end
else
begin
T1 := NodeAt(T, i);
//T1: nút đứng thứ i theo thứ tự giữa
Splay(T1);
//Đẩy T1 lên làm gốc cây
T2 := T1^.R;
//T2 = con phải T1
T1^.R := nilT; T2^.P := nilT;
//Cắt liên kết T1 – T2
Update(T1);
//Tính lại thông tin phụ trợ trong T1 sau khi cắt liên kết
end;
end;
Ghép
Vic ghép ni tip danh sách
(biu din bi cây
) vi danh sách
(biu
din bi cây
c thc hi
Nu
, danh sách
rn ta tr v
.
Nu
nh nút cc phi ca
(nút cha phn t ng
cui danh sách
), tm gi là nút y lên gc cây bng phép
chc chn không có nhánh con phi. Vic cui cùng ch là cho
làm con phi ca và tr v cây gc .
function Join(T1, T2: PNode): PNode;
begin
if T1 = nilT then Result := T2
//T1 rỗng thì trả về T2
else
begin
while T1^.R <> nilT do T1 := T1^.R;
//Đi xuống nút cực phải T1
Splay(T1);
//Đẩy lên gốc cây
SetR(T1, T2);
//Cho T2 làm con phải T1
Update(T1);
//Cập nhật lại thông tin phụ trợ trong T1
Result := T1;
//Trả về cây biểu diễn danh sách đã ghép
end;
end;
Chú ý rng sau phép ghép cây
và
thành mt cây , cây
và
phi coi
hc s dng na.
Chèn, xóa, cập nhật và truy vấn
d t các phép bia
tách và ghép.
chèn phn t vào v trí , ta tách cây biu din danh sách thành hai cây
. Cây
biu din danh sách gm phn t u tiên và cây
biu
din danh sách gm các phn t còn li. To nút cha phn t và cho
lt là con trái và con phi nút . Vic cui cùng là cp nht li thông tin
ph tr trong nút và tr v cây gc biu din danh sách m
chèn phn t .
xóa phn t ti v trí nh nút cha phn t ng th , thc hin
y lên gc cây, ct ri nhánh con trái
và nhánh con phi
ca c hin ghép
vi
c cây biu din danh sách mi sau
n t th . Vic cui cùng là gii phóng b nh cp cho nút .
cp nht giá tr phn t ti v trí nh nút cha phn t ng th
y lên gc cây bng lnh
p nht giá tr phn t
trong ng thi cp nht li các thông tin ph tr ca nút .
tính tng các phn t t v trí ti v trí , ta tách cây biu din danh sách
thành ba cây: Cây
biu din danh sách gm phn t u dãy, cây
biu din danh sách gm các phn t nm trong phm vi truy vn t ti và
cây
biu din danh sách t phn t th n cui. Cui cùng ta tr v
giá tr và tin hành ghép 3 cây lc ra phép truy vn này
có th tr li mà không cn dng các
n hóa vit.
2.1.6. Cài đặt
LISTQUERY.PAS
{$MODE OBJFPC}
program SumQueries;
type
PNode = ^TNode;
TNode = record
//Cấu trúc nút
value: Integer;
P, L, R: PNode;
len: Integer;
sum: Int64;
end;
var
sentinel: TNode;
root, nilT: PNode;
procedure Init;
begin
nilT := @sentinel;
nilT^.len := 0;
nilT^.sum := 0;
root := nilT;
end;
procedure Update(x: PNode);
//Cập nhật thông tin phụ trợ trong nút x từ hai nút con
begin
x^.len := x^.L^.len + x^.R^.len + 1;
x^.sum := x^.L^.sum + x^.R^.sum + x^.value;
end;
procedure SetL(x, y: PNode);
//Đặt y làm cont trái x
begin
y^.P := x; x^.L := y;
end;
procedure SetR(x, y: PNode);
//Đặt y làm con phải x
begin
y^.P := x; x^.R := y;
end;
//Tìm nút thứ i trong cây gốc x
function NodeAt(x: PNode; i: Integer): PNode;
var
ord: Integer;
begin
repeat
ord := x^.L^.len + 1;
if ord = i then Break;
if i < ord then
x := x^.L
else
begin
i := i - ord;
x := x^.R;
end;
until False;
Result := x;
end;
procedure UpTree(x: PNode);
//Đẩy x lên cao hơn 1 mức bằng phép quay
var
y, z: PNode;
begin
y := x^.P;
z := y^.P;
if x = y^.L then
//Quay phải
begin
SetL(y, x^.R);
SetR(x, y);
end
else
//Quay trái
begin
SetR(y, x^.L);
SetL(x, y);
end;
if z^.L = y then SetL(z, x) else SetR(z, x);
Update(y); Update(x)
//Cập nhật thông tin phụ trợ trong x và y
end;
procedure Splay(x: PNode);
//Đẩy x lên thành gốc cây
var
y, z: PNode;
begin
repeat
y := x^.P;
if y = nilT then Break;
z := y^.P;
if z <> nilT then
if (y = z^.L) = (x = y^.L) then UpTree(y)
else UpTree(x);
UpTree(x);
until False;
end;
//Tách cây T thành 2 cây T1, T2, cây T1 gồm i phần tử đầu, cây T2 gồm các phần tử còn lại
procedure Split(T: PNode; i: Integer; var T1, T2: PNode);
begin
if i = 0 then
//i = 0, cây T1 rỗng
begin
T1 := nilT; T2 := T;
end
else
begin
T1 := NodeAt(T, i);
//Nhảy đến nút thứ i
Splay(T1);
//Đẩy lên gốc
T2 := T1^.R;
//Cắt nhánh con phải ra làm T2
T1^.R := nilT; T2^.P := nilT;
Update(T1);
//Cập nhật thông tin phụ trợ trong T1
end;
end;
function Join(T1, T2: PNode): PNode;
//Ghép nối tiếp hai danh sách T1, T2
begin
if T1 = nilT then Result := T2
else
begin
while T1^.R <> nilT do T1 := T1^.R;
//Nhảy đến nút cực phải của T1
Splay(T1);
//Đẩy lên gốc
SetR(T1, T2);
//Cho T2 làm con phải
Update(T1);
//Cập nhật thông tin phụ trợ
Result := T1;
end;
end;
//Các thao tác chính trên danh sách
procedure Insert(i: Integer; v: Integer);
//Chèn v vào vị trí i
var
T1, T2: PNode;
begin
if i > root^.len then i := root^.len + 1;
Split(root, i - 1, T1, T2);
//Tách thành hai danh sách con tại vị trí chèn
New(root);
//Tạo gốc mới chứa phần tử chèn vào
root^.value := v;
root^.P := nilT;
SetL(root, T1); SetR(root, T2);
//Cho hai danh sách con vào hai bên
Update(root);
//Cập nhật thông tin phụ trợ
end;
procedure Delete(i: Integer);
//Xóa phần tử thứ i
var
x, T1, T2: PNode;
begin
x := NodeAt(root, i);
//Nhảy tới nút chứa phần tử cần xóa
Splay(x);
//Đẩy lên gốc
T1 := x^.L; T1^.P := nilT;
T2 := x^.R; T2^.P := nilT;
Dispose(x);
//Giải phóng bộ nhớ
root := Join(T1, T2);
//Ghép nối tiếp hai danh sách hai bên vị trí xóa
end;
procedure Update(i: Integer; v: Integer);
//Cập nhật giá trị phần tử thứ i
begin
root := NodeAt(root, i);
//Nhảy tới nút chứa phần tử thứ i
Splay(root);
//Đẩy lên gốc
root^.value := v;
//Đặt giá trị mới
Update(root);
//Cập nhật lại thông tin phụ trợ (sum)
end;
function Query(i, j: Integer): Int64;
//Tính tổng các phần tử từ i tới j
var
T1, T2, T3: PNode;
begin
Split(root, j, T2, T3); Split(T2, i - 1, T1, T2);
//Tách thành 3 danh sách nối tiếp T1, T2,T3
Result := T2^.sum;
//Trả về tổng các phần tử trong T2
Root := Join(Join(T1, T2), T3);
//Ghép lại
end;
procedure Solve;
var
c: Char;
k, p: Integer;
i, j: Integer;
v: Integer;
begin
ReadLn(k);
for p := 1 to k do
begin
Read(c);
case c of
'I':
begin
ReadLn(i, v);
Insert(i, v);
end;
'D':
begin
ReadLn(i);
Delete(i);
end;
'U':
begin
ReadLn(i, v);
Update(i, v);
end;
'Q':
begin
ReadLn(i, j);
WriteLn(Query(i, j));
end;
end;
end;
end;
procedure FreeMemory(x: PNode);
begin
if x = nilT then Exit;
FreeMemory(x^.L);
FreeMemory(x^.R);
Dispose(x);
end;
begin
Init;
Solve;
FreeMemory(root);
end.
Thi gian thc hin gii thut có th ln thc hin thao tác
và s li gi hàm . Nhn xét rng mi khi phép truy cp phn t
gc xung mt lnh chuyn nút
c. Chính vì vy thi gian thc hin gii thut có th
các thao tác , s thao tác cn thc hin là mng
.
Các nghiên cu lý thuy ra rng mt phép thc hin riêng r có
th mt thi gian
vi là s nút trên cây. Tuy vy, thi gian thc hin c
dãy gm thao tác tính tng li ch là
. Tc là ta có
th coi mi phép cp nht/truy vc thc hin trong thi gian
- amortized analysis) khi .
c rng cây Splay có thi gian thc hin gii
thut trên mt dãy thao tác chèn/xóa/tìm kim i cây nh
phân tìm kim tng ký pháp O ln (sai khác
mt hng s n trong ký pháp O).
2.2. Cây quản lý đoạn
Segment trees [2] là mt cu trúc d liu c thit k cho các ng
dng hình hc. Cu trúc này khá phc tc s d tr li nhiu
loi truy vn khó. c so sánh vi interval trees là mt
dng cu trúc d lip các ch
Trong mn hóa cu trúc segment trees gii quyt bài toán
truy vn phu này làm cho cây qun ch ging vi segment
trees hình nh biu din còn các thu c tr
giu so vi cu trúc nguyên th li
c nhng truy vu trúc nguyên thy.
Trên các dio lun v thuc và th gii,
gi interval trees hoc segment trees v gi tên cu trúc này,
tuy nhiên tôi không tìm th nó trong các cun sách thut toán
ph bin [3] [1] [4]. Các bài ging thu dùng tên gi interval
trees và segment trees cp ti hai cu trúc d liu trong hình hc tính
toán. Cu trúc mà mn, tôi tm gi là cây qun lý n, ch là mt
hn ch cng hp c th.
Mi bài toán gii quyc bng cây qun u có th gic bng
cu trúc d li mc 2.1c l
Mc dù vy, cây qun cung cp mt cách qun lý mi thông qua các
p, ngoài ra vit d m ca cu trúc d
liu này. Ta gii hn li bà ng h c bit:
không có phép chèn và xóa phn t kho sát cu trúc d liu cây qun lý
n.
Bài toán: (Range Query 2).
Cho mt dãy gm s nguyên
. Xét hai phép bii:
Phép cp nht
t
Phép truy vn
: Tr v tng các phn t t
ti
Yêu cu: Cho dãy thao tác thc hin tun t, hãy tr li tt c các truy vn
Input
Dòng 1 cha 2 s
Dòng 2 cha s nguyên
dòng tip, mi dòng cho thông tin v mt phép bii. Mi dòng bt
u bi mt ký t
Nu ký t p theo là hai s nguyên ng
vi phép cp nht
(
)
Nu ký t p theo là hai s nguyên ng
vi phép truy vn
()
Output
Tr li tt c các truy vn , vi mi truy vn in ra câu tr li trên 1 dòng
Sample Input
Sample Output
9 5
1 2 3 4 5 6 7 8 9
U 1 5 //5 2 3 4 5 6 7 8 9
U 3 6 //5 2 6 4 5 6 7 8 9
Q 1 4
U 8 1 //5 2 6 4 5 6 7 1 9
Q 1 9
17
45
2.2.1. Cấu trúc
Cây qu n là mt cây nh phân (full binary trees) có cu trúc
Mi nút qun lý mng liên tip, trong nút cha thông tin
tng hp t ng mà nó qun lý ng hp c th này,
mi nút cha tng ca các phn t trong phm vi mà nó qun lý).
Nút gc qung t 1 ti .
Nu mt nút qung t ti () thì nút con trái
ca nó qung t ti và nút con phi ca nó qun lý các
ng t ti .
.
Nu mt nút ch qun lý mng thì nó s là nút lá và không có nút
con. Trong mt s ng hp cc thut toán, mng s
c gn vi mt con tr
tr ti nút lá qun lý trc ting
.
thun tin cho trình bày, vi mi nút s
và
cho
bit qun lý các phn t t trong mng t ch s
ti ch s
.
Hình 6 là ví d v cây qun gm ng
Hình 6. Cây qun
Bổ đề 1
Vi mi s sâu ca các nút lá trên cây qun gm
t quá
Chứng minh
Gi
sâu ln nht ca mt nút lá trên cây qun gm
xây dng cây: nút con trái ca nút gc qun lý
[1]
[2]
[3]
3]
[4]
[5]
[45]
6]
[46]
6]
ng và nút con phi ca nút gc qun lý
ng. Tc là nu xét
v sâu:
(1)
Rõ ràng khi , ta có
, b
Khi , ta chng minh bng thc m
.
Khi ta có
, bng th
ng hp , bng thc s c chng minh bng quy np theo :
(2)
Bổ đề 2
Vi mi s sâu ca các nút lá trên cây qun gm
ng không nh
Chứng minh
Gi
sâu nh nht ca mt nút lá trên cây qun gm
xây dng cây, ta có:
(3)
Rõ ràng khi , ta có
, b
Khi , b c chng minh bng quy np theo :
(4)
B 1 và B 2 ch ra r sâu c cao ca cây là
mng
cho phép biu di
i gian thc hin gii thut.
2.2.2. Biểu diễn
Ta s s dng m biu din cây qun quen thuc:
Nút g 1, nút có nút con trái là nút , nút con phi là nút
và nút cha nút cha
. Mun vy ta cc mng
cn khai báo.
Xét mt cây qun cao , ta thêm cho nút cc trái ca cây mt nút lá
bên trái, gi là nút . Do phép xây dng cây, nút lá này chc ch sâu
lt c ln nht.
Theo s, nút lá s có ch s
(do nó là lá cc trái và nm
sâu
B 1 ra rng cây qun lý danh sách phn t có chiu cao
s ca nút lá không bao gi t quá
y ch s các nút còn li không t quá
.
d nh ng khai báo mng vi các phn t t 1
ti .
Th tc
i to nhánh cây gc qui
ng
ti
:
procedure Build(x: Integer; low, high: Integer);
var
middle: Integer;
begin
l[x] := low; h[x] := high;
if low = high then
//Nút x là một lá quản lý duy nhất một đối tượng a[low]
begin
sum[x] := a[low]
leaf[low] := x;
end
else
//Nút x là nút nhánh và sẽ có đúng 2 nút con
begin
middle := (low + high) div 2;
Build(x * 2, low, middle);
//Khởi tạo nhánh con trái quản lý các đối tượng low…middle
Build(x * 2 + 1, middle + 1, high);
//Khởi tạo nhánh con phải quản lý các đối tượng middle + 1…high
sum[x] := sum[2 * x] + sum[2 * x + 1]);
//Tổng hợp thông tin tổng từ 2 nút con lên nút x
end;
end;
Th tc khi to cây qu n s c thc hin bng li gi
. Vic khi tc thc hin trong thi gian
.
2.2.3. Cập nhật
Thao tu tiên trên cây qun là phi cp nht li cây mi khi có s
i giá tr phn t. Khi mt phn t
b i, ta nhy ti nút
là nút lá trc tip qun lý
nút lên gc, c
nào thì cp nht li thông tin tng
. Sau quá trình này, tt c các nút
cha phn t
trong phm vi qun lý s c cp nht li thông tin tng
.
Th tc
u chnh li cây qun khi có s thay
i
procedure Update(i: Integer; v: Integer);
var
x: Integer;
begin
x := leaf[i];
//Nhảy tới nút lá quản lý trực tiếp đối tượng i
sum[x] := v;
//Cập nhật thông tin tại lá x
while x > 1 do
//Chừng nào x chưa phải là gốc
begin
x := x div 2;
//Nhảy lên nút cha của x rồi cập nhật thông tin tổng
sum[x] := sum[2 * x] + sum[2 * x + 1];
end;
end;