1. Trang chủ
  2. » Luận Văn - Báo Cáo

Chuyên đề cấu trúc dữ liệu đặc biệt

17 284 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 17
Dung lượng 281,5 KB

Nội dung

Trên cây interval tree có hai thao tác quan trọng− Thao tác cập nhật thông tingọi truy vấn 1 trên đoạn [i..j] − Thao tác khai thác thông tingọi truy vấn 2 trên đoạn [i..j] Ứng dụng của c

Trang 1

HỘI THẢO KHOA HỌC CÁC TRƯỜNG THPT CHUYÊN KHU VỰC DUYÊN HẢI & ĐỒNG BẰNG BẮC BỘ

LẦN THỨ VIII

CHUYÊN ĐỀ BỒI DƯỠNG HỌC SINH GIỎI

Người thực hiện: ÔN QUANG HÙNG

Đơn vị: Trường THPT Chuyên Nguyễn Bỉnh Khiêm - tỉnh Quảng Nam.

Quảng Nam, tháng 8 năm 2015

Trang 2

INTERVAL TREE(IT)

A PHẦN LÝ THUYẾT

Interval tree (cây đoạn) là một cây nhị phân mỗi nút không phải là node lá đều có hai nút con

Giả sử nút A lưu thông tin của đoạn từ i j thì 2 nút con của nó: A1; A2, lần lượt lưu thông tin của các đoạn i m và m+1 j, với m=(i+j) div 2 là phần tử giữa đoạn

Để đơn giản ta dùng mảng 1 chiều T để biểu diễn cây với ý nghĩa:

− Nút 1 là nút gốc

− Nút d(nếu không là nút lá) thì có nút con trái: 2*d và nút con phải 2*d+1

− Nút 1 lưu thông tin các đoạn 1 n(n: độ dài dãy số)

Vậy dễ hiểu nút 2 lưu thông tin đoạn [1 (n+1) div 2] và nút 3 sẽ lưu thông tin đoạn [(n+1) div 2+1 n]

Một cách đệ quy thì ta thấy nút thứ d sẽ lưu thông tin của 1 đoạn xác định nào đấy Ví dụ với n=5 có đoạn [1 n]

Trang 3

Trên cây interval tree có hai thao tác quan trọng

− Thao tác cập nhật thông tin(gọi truy vấn 1) trên đoạn [i j]

− Thao tác khai thác thông tin(gọi truy vấn 2) trên đoạn [i j]

Ứng dụng của cây IT

Cây IT cho phép cập nhật và tìm kiếm các đoạn, khoảng rất hiệu quả

Cây IT còn kết hợp với cấu trúc Heap hoặc AVL để giải quyết một số bài toán Đối với những bài toán liên quan đến dãy số; những dạng bài toán quy về dãy số; bài toán hình học, đặc biệt những việc mà thường xuyên biến đổi và nhiều câu hỏi (truy vấn) xen kẻ, thì cây IT rất hữu dụng

Ví dụ:

Cho một dãy số nguyên A[1 N] gồm N phần tử(N<=105) Có M truy vấn gồm hai loại:

• Ci j: Thay phần tử thứ i bằng giá trị j

• Qi j: Xuất ra tổng các phần tử trong dãy số từ vị trí i đến vị trí j

Nhiệm vụ: Cho trước dãy số A[1 N] và M truy vấn trong file văn bản

DAYSO.INP Hãy thực hiện các phép biến đổi trên dãy và ghi các kết quả ra file DAYSO.OUT

Ví dụ

5 3

1 2 3 4 5

Q 2 3

C 3 7

Q 1 4

5 14

Dùng cây IT để giải quyết vấn đề như sau:

 Truy vấn 1:

Thủ tuc truyvan1(l,r,i,d:longint): trong đó l(đầu đoạn) và r(cuối đoạn); d(node

chứa dữ liệu); còn i là vị trí hay con gọi là phần tử thứ i mà cần gán giá trị v

Mỗi đoạn [l r] sẽ có 3 khả năng so với đoạn [i i] (sử dụng đoạn [i,i] cho dễ so sánh)

o TH1: [l r] [i,i] =Φ thì bỏ qua không làm gì cả (exit)

Trang 4

o TH2: [l r] =[i,i] (vừa khít hay l=r) thì ta gán T[d]:=v, lúc này v là giá trị lớn nhất trên đoạn [i,i](d là node lá thì ta gán giá trị v vào)

o TH3: [l r] không nằm trong [i,i] thì ta sang node con trái và node con phải để cập nhật sau khi cập nhật xong hai node con thì tiếp theo tính cập nhật cho node cha Một cách đệ quy thì chắc hẳn phải gặp một trong hai trường hợp trên

Cứ mỗi truy vấn 1 thì ta cập nhật được giá trị v vào cây IT

Lời gọi truy vấn 1 bắt đầu từ node gốc truyvan1(1,n,i,1);

Thuật toán như sau:

{==========================================================} procedure truyvan1(l,r,i,d:longint);

var mid:longint;

begin

if (i<l) or (r<i) then exit;

if (l=r) then

begin

T[d]:=v;

exit;

end;

mid:=(l+r) div 2;

truyvan1(l,mid,i,2*d);

truyvan1(mid+1,r,i,2*d+1);

T[d]:=sum(T[2*d],T[2*d+1]);

end;

{==========================================================}

 Truy vấn 2:

Dựa vào cây IT do truy vấn 1 đã được xây dựng và nhiệm vụ lúc này thủ tục

truyvan2(L,R,i,j,d:longint) lấy kết quả trên đoạn [i j]

Mỗi đoạn [l r] sẽ có 3 khả năng so với đoạn [i j]

o TH1: [l r] [i,j] =Φ thì bỏ qua không làm gì cả (exit)

o TH2: [l r] =[i,j] (vừa khít) thì ta tối ưu kết quả khi so sánh với T[d] như tính tổng Inc(sum,T[d]) mà không cần đi vào các node của nó

o TH3: ([l r] không nằm trong [i,j] tức có 1 phần chung nào đó) thì ta phải

đi vào hai node con của nó để lấy kết quả Một cách đệ quy thì chắc hẳn phải gặp một trong hai trường hợp trên

Cuối cùng ta có được kết quả sum cần tìm

Cũng tương tự như truy vấn 1, lời gọi truy vấn 2 bắt đầu từ node gốc

truyvan2(i,j,1,n,1)

Thuật toán như sau:

{==========================================================}

Trang 5

procedure truyvan2(L,R,i,j,d:longint);

var mid:longint;

begin

if (j<l) or (i>r) then exit;

if (i=L)and(j=R) then

begin

inc(res,t[d]);

exit;

end;

mid:=(L+R) div 2;

truyvan2(L,mid,i,mid,2*d);

truyvan2(mid+1,R,mid+1,j,2*d+1);

end;

{==========================================================}

Nhận xét:

Ta nhận thấy mỗi truy vấn độ phức tạp xấp xỉ O(log(n))

Như vậy bài này nếu dùng interval tree độ phức tạp xấp xỉ O(mxlog(n))

Trang 6

B PHẦN BÀI TẬP VẬN DỤNG Bài 1

Cho một dãy số A[1 N] gồm N số nguyên đánh số từ 1 đến N là A[1], A[2], ,

A[N] Xét M yêu cầu gồm hai loại:

• Ci j: Thay phần tử thứ i bằng giá trị j

• Qi j: Xuất ra phần tử lớn nhất trong dãy số từ vị trí i đến vị trí j

Nhiệm vụ: Cho trước dãy số A[1 N] và M yêu cầu trong file văn bản

MAXIJ.INP Hãy thực hiện các phép biến đổi trên dãy và viết các kết quả ra file MAXIJ.OUT

Dữ liệu vào: file MAXIJ.INP

- Dòng đầu tiên chứa hai số nguyên N, M

- Dòng thứ hai chứa các phần tử của dãy A[1 N] M dòng cuối chứa các yêu cầu

Dữ liệu ra: file MAXIJ.OUT gồm một số dòng tương ứng là kết quả của các yêu

cầu Q trong dữ liệu vào

Ví dụ:

5 3

5 4 3 2 1

Q 1 3

C 3 7

Q 2 4

5 7

Giới hạn: 1≤ N≤ 100000; |Ai|≤ 1000, M≤ 100000

Ý tưởng

Đối với truy vấn 1 mỗi giá trị cần thay đổi vào thì ta cập nhật lên cây interval

tree

Đối với truy vấn 2 vì node gốc lưu giá trị lớn nhất toàn cây cho nên ta bắt đầu

từ node này và gọi đệ quy maxij(1,n,u,v,1); để lấy kết quả

CODE

uses crt, math;

const fi='MAXIJ.INP';

fo='MAXIJ.OUT';

maxn=trunc(1e5);

var

T:array[1 5*maxn] of longint;

ch:char;

m,n,i,u,v,res:longint;

Trang 7

f,g:text;

procedure truyvan1(l,r,i,d:longint);{cap nhat mang t}

var mid:longint;

begin

if (i<L) or (r<i) then exit;

if (L=R) then

begin

T[d]:=v;

exit;

end;

mid:=(L+R) div 2;

truyvan1(l,mid,i,2*d);

truyvan1(mid+1,r,i,2*d+1);

T[d]:=max(T[2*d],T[2*d+1]);

end;

{==========================================================} procedure truyvan2(L,R,i,j,d:longint);

var mid:longint;

begin

if (j<l) or (i>r) then exit;

if (i=L)and(j=R) then

begin

res:=max(res,t[d]);

exit;

end;

mid:=(L+R) div 2;

truyvan2(L,mid,i,min(mid,j),2*d);

truyvan2(mid+1,R,min(i,mid+1),j,2*d+1);

end;

{==========================================================} begin

assign(f,fi); reset(f);

assign(g,fo); rewrite(g);

readln(f,n,m);

for i:=1 to n do

begin

read(f,v);

truyvan1(1,n,i,1);

end;

readln(f);

Trang 8

res:=low(longint);

for i:=1 to m do

begin

readln(f,ch,u,v);

case ch of

'Q':begin

truyvan2(1,n,u,v,1);

writeln(g,res);

res:=low(longint);

end;

'C':truyvan1(1,n,u,1);

end;

end;

close(f);

close(g);

end

Bài 2

Cho một dãy gồm N phần tử, giá trị ban đầu mỗi phần tử bằng 0

Cho m phép biến đổi, mỗi phép có dạng (u, v, k) tăng mỗi phần tử từ vị trí u đến

vị trí v lên k đơn vị

Với q câu hỏi, mỗi câu có dạng (u, v): cho biết phần tử có giá trị lớn nhất trên đoạn [u, v]

Dữ liệu vào: file QMAX.INP

- Dòng đầu tiên chứa hai số nguyên N, M

- m dòng tiếp theo, mỗi dòng chứa u, v, k là cho biết một phép biến đổi

Dòng thứ m+2 là q

- q dòng tiếp theo, mỗi dòng chứa u, v cho biết một phép biến đổi

Dữ liệu ra: file QMAX.OUT gồm q dòng tương ứng là kết quả của các yêu cầu

trong dữ liệu vào

Ví dụ:

6 2

1 3 2

4 6 3 1

3 4

3

Giới hạn: 1≤ N≤ 100000; |Ai|≤ 1000, M≤ 100000

Nhận xét

Trang 9

− Bài này không nên vận dụng máy móc nếu ta dùng kĩ thuật IT tức là ta cập nhật trên đoạn [i, j] trước thì độ phức tạp của việc cập nhật O(mx(vu+ 1 )xlog(n))

− Cho nên ta dùng cách rãi sỏi hai đầu với m lần, mỗi lần

a[u] a[u]+k

a[v 1] a[v 1]-k

=

Tiếp theo : a[i]=a[i]+a[i-1] , với i=1 m

Như vậy độ phức tạp lúc này O(m+n)

 Từ mảng A đó ta mới bắt đầu cập nhật lên cây thì độ phức tạp O(log(n))

 Còn q câu hỏi thì ta vận dụng truy vấn trên cây IT bắt đầu truyvan(1,1,n,u,v)

sẽ có kết quả để trả lời cho từng câu hỏi của đề bài

Lưu ý: Bài tập này có thể giải quyết bằng BIT.

Với bài này thì độ phức tạp O ((m+q) log n)

CODE

uses crt, math;

const fi='QMAX.INP';

fo='QMAX.OUT';

maxn=trunc(1e6);

var

T,A:array[0 maxn] of longint;

m,n,q:longint;

procedure modify(l,r,d:longint);

var mid:longint;

begin

if l=r then

begin

T[d]:=a[L];

exit;

end;

mid:=(l+r) div 2;

modify(l,mid,d*2);

modify(mid+1,r,d*2+1);

T[d]:=max(T[d*2],T[d*2+1]);

end;

{=================================================}

procedure find(l,r,u,v,d:longint; var GTLN:longint);

var mid,maxL,maxR:longint;

begin

if (v<l) or (r<u) then

Trang 10

begin

GTLN:=low(longint);

exit;

end;

if (l=u) and (r=v) then

begin

GTLN:=T[d];

exit;

end;

mid:=(l+r) div 2;

find(l , mid ,u,min(v,mid),d*2 ,maxL);

find(mid+1, r ,max(mid+1,u),v,d*2+1 ,maxR);

GTLN:=max(maxL,maxR);

end;

{=================================================}

procedure xuli;

var i,j,u,v,k,GTLN:longint;

begin

readln(n,m);

for i:=1 to m do

begin

readln(u,v,k);

a[u]:=a[u]+k;

a[v+1]:=a[v+1]-k;

end;

for i:=1 to n do

a[i]:=a[i]+a[i-1];

modify(1,n,1);

readln(q);

for i:=1 to q do

begin

readln(u,v);

find(1,n,u,v,1,GTLN);

writeln(GTLN);

end;

end;

{=================================================}

begin

assign(input,fi); reset(input);

assign(output,fo); rewrite(output);

Trang 11

xuli;

close(input);

close(output);

end

Bài 3

Tương tự như bài 2

Dữ liệu vào file QMAX2.INP

- n là số phần tử của dãy

- m là số lượng biến đổi và câu hỏi

+ biến đổi có dạng: 0 x y value

+ câu hỏi có dạng: 1 x y

Dữ liệu ra file QMAX2.OUT

Ghi ra trả lời cho lần lượt từng câu hỏi

Ví dụ:

6 3

0 1 3 3

0 4 6 4

1 1 6

4

Giới hạn: (n<=50000) và (m<=100000)

Ý tưởng

Tuy tương tự như bài 2 nhưng cách xử lí phải khác một chút;

Nhận xét: bài này ta không thể cập nhật lên cây rồi truy vấn bởi vì phép biến đổi và

câu hỏi lẫn lộn Nếu như vậy độ phức tạp không thể là O(log(n)) nữa Do đó ta phải cài đặt như sau:

Gọi T[i] là GTLN trên đoạn mà node i quản lí và T cũng là cây IT.

Khi gặp một phép biến đổi thì cập nhật lên cây nếu như khi gặp một node

nào đó vừa khít với đoạn [u’, v’] thì không nên đi vào các node con của nó (không thì độ phức tạp sẽ tăng lên) và ở đây ta dùng mảng Pos để lưu lại giá trị cần tăng lên cho các phần tử mà nó quản lí, mỗi khi đi xuống các phần tử con thì ta mang cả giá trị của node cha (i) tăng lên pos[i] đơn vị cho các node con và các node con (mảng Pos) cũng lấy từ cha xuống để chuẩn bị cho cuộc hành trình mới; nhưng lưu ý cứ mỗi lần đi xuống như vậy thì ta khởi tạo lại Pos[i]=0 để tránh trường hợp cộng lại nhiều lần; cuối cùng giá trị lớn nhất luôn cập nhật lên node root

Khi gặp câu hỏi thì truy vấn trên cây IT như mọi lần ta làm.

CODE

uses math,crt;

Trang 12

const fi='QMAX2.INP';

fo='QMAX2.OUT';

maxn=trunc(1e6);

var

T,pos:array[0 maxn] of longint;

n,m:longint;

procedure down(i:longint);

begin

inc(pos[2*i],pos[i]);

inc(pos[2*i+1],pos[i]);

inc(t[2*i],pos[i]);

inc(t[2*i+1],pos[i]);

pos[i]:=0;

end;

{==================================================}

procedure update(l,r,u,v,i,c:longint);

var mid:longint;

begin

if (r<u) or (v<l) then

exit;

if (l=u) and (v=r) then

begin

inc(pos[i],c);

inc(T[i],c);

exit;

end;

mid:=(l+r) div 2;

down(i);

update(l,mid,u,min(v,mid),i*2,c);

update(mid+1,r,max(mid+1,u),v,i*2+1,c);

T[i]:=max(t[i*2],t[i*2+1]);

end;

{==================================================}

procedure find(i,l,r,u,v:longint; var GTLN: longint);

var mid,maxL,maxR:longint;

begin

if (r<u) or (v<l) then

begin

GTLN:=0;

Trang 13

exit;

end;

if (l=u) and (v=r) then

begin

GTLN:=T[i];

exit;

end;

mid:=(l+r) div 2;

down(i);

find(i*2,l,mid,u,min(mid,v),maxL);

find(i*2+1,mid+1,r,max(mid+1,u),v,maxR);

GTLN:=(max(maxL,maxR));

end;

{==================================================}

procedure xuli;

var i,u,v,c,ch,GTLN:longint;

begin

readln(n,m);

for i:=1 to m do

begin

read(ch);

if ch=0 then

begin

readln(u,v,c);

update(1,n,u,v,1,c);

end

else

begin

readln(u,v);

find(1,1,n,u,v,GTLN);

writeln(GTLN);

end;

end;

end;

{==================================================}

begin

assign(input,fi); reset(input);

assign(output,fo); rewrite(output);

xuli;

close(input);

Trang 14

close(output);

end

Bài 4

Cho một dãy số A[1 N] gồm N số nguyên đánh số từ 1 đến N là A[1], A[2], ,

A[N] Yêu cầu có m truy vấn ứng với mỗi truy vấn hãy xác định độ chênh lệch giữa các phần tử nhỏ nhất và lớn nhất trong dãy số từ vị trí i đến vị trí j

Dữ liệu vào: file DIFF.INP

- Dòng đầu tiên chứa hai số nguyên N, M

- Dòng thứ hai chứa các phần tử của dãy A[1 N] M dòng cuối chứa các yêu cầu

Dữ liệu ra: file DIFF.OUT gồm m dòng tương ứng là kết quả của các yêu cầu

trong dữ liệu vào

Ví dụ:

5 3

2 7 5 1 9

1 3

3 3

2 5

5 0 8

Giới hạn: 1≤ N≤ 100000; |Ai|≤ 1000, M≤ 100000

Ý tưởng

Với bài này chúng ta sử dụng hai cây IT: một cây Tmin và cây thứ hai Tmax Hoặc dùng một cây Tmix mỗi phần tử có hai trường: GTmin và GTmax thì cũng tương tự như hai cây nhưng ở đây ta ghép thành một cây

 Tạo cây như sau:

if l=r then

begin

Tmin[d]:=A[L];

Tmax[d]:=A[L];

Exit;

end

else

begin

< >

Tmin[d]:=min(Tmin[d*2],Tmin[d*2+1]);

Tmax[d]:=max(Tmax[d*2],Tmax[d*2+1]);

end;

 Truyvan thì đơn giản rồi ta vận dụng truy vấn cây IT là sẽ được kết quả theo yêu cầu của bài

Trang 15

Một số bài tập khác

http://vn.spoj.com/problems/QMAX3VN/

http://vn.spoj.com/problems/QMAX4/

http://vn.spoj.com/problems/LITES/

http://vn.spoj.com/problems/MARBLE/

Trang 16

C KẾT LUẬN

Interval tree là một trong những cấu trúc dữ liệu đặc biệt, nó giúp ta có thể giải được nhiều bài toán trong thời gian cho phép Độ phức tạp thông thường khi làm việc với Interval là O(logN) Có hai thao tác quan trọng:

 Cập nhật giá trị vào vị trí i hoặc trên một đoạn[i, j] rất nhanh chóng của một dãy

 Khai thác trên dãy số (có số lượng phần tử lớn) trong một thời gian ngắn

Trong thời gian ngắn vừa tìm hiểu và vừa viết chuyên đề này nên không thể tránh khỏi thiếu sót mong sự góp ý của thầy cô và các em học sinh để chuyên đề này hoàn thiện hơn

Ngày đăng: 19/01/2016, 19:05

TỪ KHÓA LIÊN QUAN

w