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

CẤU TRÚC dữ LIỆU NÂNG CAO

27 351 1

Đ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

CHUYÊN ĐỀ: CẤU TRÚC DỮ LIỆU NÂNG CAO Interval Tree công cụ hữu dụng sử dụng nhiều toán dãy số, quy toán xử lí dãy số, đặc biệt toán có nhiều công việc cần xử lí nhiều truy vấn xen kẽ Phần lí thuyết Interval Tree trình bày rõ ràng nhiều tài liệu chuyên gia, đồng nghiệp dạy bồi dưỡng học sinh giỏi chia sẻ, nên mạn phép không đề cập Do lực có hạn nên không viết nghĩ tập mà có sử dụng Interval Tree để giải Vì thế, chuyên đề thực chất tập sưu tầm, biên tập thành tập tài liệu để phục vụ công tác giảng dạy bồi dưỡng HSG môn Tin học Ở đây, trích dẫn tập nguồn từ SPOJ, Codeforce nhiều nguồn khác Với tập đề cập đến ba vấn đề: • Tóm tắt đề rõ ràng • Thuật toán tốt • Code demo (nếu có) Khi áp dụng tài liệu vào giảng dạy, thường bỏ phần “code demo” để không “làm hỏng học sinh”, phát đề cho học sinh Với tập, sau học sinh nghiên cứu đề xuất ý tưởng (hoặc code nộp mà chưa AC), dẫn dắt, đưa giải thuật toán để học sinh “ngấm” toán Dần dần học sinh nắm tư tưởng Interval Tree ứng dụng linh động vào toán khác Tôi xin trích dẫn tài liệu tham khảo để biên tập thành chuyên đề này: • • • • • http://laptrinh.ntu.edu.vn/Problem/List http://codeforces.com/problemset http://vn.spoj.com/problems/oi/ https://onlylove97.wordpress.com/category/it/ https://doraemonvodanh.wordpress.com/category/thuat-toan/segment-tree/bai- tap-interval-tree/ • Quyển: Một số vấn đề ý môn Tin học – Nhóm tác giả Đại học Vinh Ứng dụng Interval Tree để giải toán sau: Bài Phần tử thứ K http://vn.spoj.com/problems/YPKTH/ Cho dãy số A có N phần tử nguyên phân biệt Cho Q truy vấn, truy vấn có dạng: L R K Yêu cầu: truy vấn xuất phần tử lớn thứ K sau xếp phần tử AL, AL+1, …, AR theo thứ tự tăng dần Giới hạn: ≤ N, Q ≤ 105 |Ai| ≤ 109 với ≤ i ≤ N 1≤L≤R≤N ≤ K ≤ R-L+1 Input: - Dòng chứa số N - Dòng chứa N số A1, A2, …, AN - Dòng chứa số Q - Q dòng tiếp theo, dòng chứa số L, R, K Output: Q dòng, dòng chứa câu trả lời cho truy vấn theo thứ tự nhập vào Ví dụ: Input Output 2154368 4 122 374 462 551 Thời gian chạy: 1s-3s THUẬT TOÁN : Dùng Segment Tree với nút lưu lại dãy từ l->r sort Dùng vector cho nút để giảm nhớ: nút xuất logN lần cây, nhớ NlogN Có thể tạo O(NlogN), lần hợp hai nút lại ta trộn hai đoạn O(n+m) với n, m kích thước hai đoạn Với truy vấn ta làm sau: Xét giá trị (gọi res) có dãy cách chặt nhị phân, (nút thực chất sort dãy tăng dần nên chặt nhị phân nút 1), đếm xem đoạn l r có phần tử nhỏ nó, nhỏ k tức phải tìm số lớn tương tự Với lần truy vấn l r ta lại chặt nhị phân nút nằm đoạn l r để tìm phần tử lớn ≤ res đồng thời kiểm tra xem res có mặt đếm số lượng phần tử nhỏ res (Chú ý phần tử phân biệt) Điều kiện để res nghiệm cnt == k-1 (cnt số lượng số < res) tìm thấy res đoạn l r Code demo: http://ideone.com/GTScHq #include using namespace std; typedef long long ll; typedef int64_t ll; typedef pair ii; #define EL printf("\n") #define pb push_back #define mp make_pair #define X first #define Y second typedef vector data; const int N = 100100; int n, q, a[N], L, R, k, res, cnt, f; data t[4*N], nil; data combine(data u, data v) { data ans = nil; int i = 0, j = 0; while (i < u.size() and j < v.size()) { if (u[i] < v[j]) ans.pb(u[i++]); else ans.pb(v[j++]); } while (i < u.size()) ans.pb(u[i++]); while (j < v.size()) ans.pb(v[j++]); return ans; } void build(int k, int l, int r) { if (l == r) { void get(int node, int l, int r) { if (r < L or R < l) return ; if (L ≤ l and r ≤ R) { int i = 0, j = t[node].size()-1, pos = -1; while (i ≤ j) { int mid = (i+j)/2; if (t[node][mid] ≤ res) { pos = mid; i = mid+1; } else j = mid-1; } if (pos == -1) return ; if (t[node][pos] == res) f = true; cnt += pos + 1; if (t[node][pos] == res) cnt ; return ; } int mid = (l+r)/2; get(node*2,l,mid); get(node*2+1,mid+1,r); } int main() { //freopen("YPKTH.INP","r",stdin); //freopen("YPKTH.OUT","w",stdout); scanf("%d", &n); for (int i=1;i≤n;i++) scanf("%d", &a[i]); build(1,1,n); t[k].pb(a[l]); return ; scanf("%d", &q); while (q ) { scanf("%d%d%d", &L,&R,&k); int l = 0, r = t[1].size()-1; while (l ≤ r) { int mid = (l+r)/2; res = t[1][mid]; cnt = 0; f = 0; get(1,1,n); if (cnt == k-1 and f) { printf("%d\n", res); break; } if (cnt < k) l = mid+1; else r = mid-1; } } return 0; } int mid = (l+r)/2; build(k*2, l, mid); build(k*2+1, mid+1, r); t[k] = combine(t[k*2], t[k*2+1]); } } Bài Đoạn có tổng lớn http://vn.spoj.com/problems/GSS/ Cho dãy số a[1], a[2], , a[n] (|a[i]| ≤ 15000, n ≤ 50000) Hàm q(x, y) = max { tổng(a[i]+a[i+1]+ +a[j]), x ≤ i ≤ j ≤y } Cho m câu hỏi dạng x, y (1 ≤ x ≤ y ≤ n), (m ≤ 50000) -> tính q(x, y) Input - Dòng đầu n - Dòng thứ hai dãy a - Dòng thứ m - m dòng dòng cặp số x, y Output Lần lượt ghi q(x, y) tương ứng Mỗi kết ghi dòng Example Input: -1 12 Output: Thời gian chạy: 0.100s Thuật toán: Sử dụng Segment Tree Một nút lưu giá trị : sum : tổng đoạn pre : tổng lớn đoạn tiền tố suf : tổng lớn đoạn hậu tố ans : tổng lớn đoạn Công thức hợp hai nút sau : res.sum = l.sum + r.sum; res.pre = max(l.pre, l.sum + r.pre); res.suf = max(r.suf, r.sum + l.suf); res.ans = max(l.ans, r.ans, l.suf + r.pre); Code demo: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include data make_data (int x) { data res; res.sum = x; res.pre = res.suf = res.ans = x; return res; } void make_tree(int k, int l, int r) { if (l == r) { t[k] = make_data(a[l]); return ; } int mid = (l+r)/2; make_tree(k*2, l, mid); make_tree(k*2+1, mid+1, r); using namespace std; t[k] = combine(t[k*2], t[k*2+1]); typedef long long ll; } typedef int64_t typedef double const int const int const ll const real ll; real; base = 1000000007; oo = INT_MAX; ooo = LONG_LONG_MAX; pi = acos(-1.0); data query(int k, int l, int r, int L, int R) { if (l == L and r == R) return t[k]; int mid = (l+r)/2; if (R ≤ mid) return query(k*2, l, mid, L, R); #define openf {freopen("INP.INP","r",stdin);freopen("OU T.OUT","w",stdout);} #define closef {fclose(stdin);fclose(stdout);} #define readln scanf("\n") #define writeln printf("\n") if (L > mid) return query(k*2+1, mid+1, r, L, R); return combine ( query(k*2, l, mid, L, mid), query(k*2+1, mid+1, r, mid+1, R) ); // -/ / } struct data { int sum, pre, suf, ans; }; int main() { //openf; const int maxn = 100000, maxt = 4*maxn; int n, a[maxn], m, L, R; data t[maxt]; data combine (data l, data r) { data res; res.sum = l.sum + r.sum; res.pre = max(l.pre, l.sum + r.pre); res.suf = max(r.suf, r.sum + l.suf); res.ans = max( max(l.ans, r.ans), l.suf + r.pre); return res; } scanf("%d", &n); for (int i=1;i≤n;i++) scanf("%d", &a[i]); make_tree(1,1,n); scanf("%d", &m); while (m ) { scanf("%d%d",&L,&R); printf("%d\n",query(1,1,n,L,R).ans); } //closef; return 0; } Bài Diện tích hình chữ nhật - http://vn.spoj.com/problems/AREA/ Trên mặt phẳng toạ độ người ta vẽ N hình chữ nhật Hãy tính diện tích che phủ N hình chữ nhật này, biết N hình chữ nhật song song với trục Ox Oy Input Dòng : Số nguyên N ( ≤ N ≤ 10000 ) N dòng tiếp theo, dòng gồm số nguyên x1, y1, x2, y2 tương ứng toạ độ góc trái góc phải hình chữ nhật thứ i.( ≤ x1 ≤ x2 ≤ 30000, ≤ y1 ≤ y2 ≤ 30000 ) Output Gồm dòng ghi diện tích phủ N hình chữ nhật Example Input: 10 10 20 20 15 15 25 30 Output: 225 Thời gian chạy: 0.100s Thuật toán: Sử dụng Segment Tree (IT) Chuyển liệu đề cho sang dãy tọa độ x, x có lưu lại y1 y2 tương ứng hàng giới hạn trên, đồng thời lưu lại type -1 hay tương ứng cạnh đóng hay mở Sau sort lại mảng theo x Mục đích cách xử lí khoảng từ xi -> xi+1 xét dãy sort ta tính phần diện tích bao phủ y1 y2 Lúc ta dùng Segment Tree, nút lưu lại cnt số lượng đoạn phủ len tổng chiều dài Code demo: http://ideone.com/tGGNUI #include #include #include #include #include #include #include #include void update(int k, int l, int r, int L, int R, int type) { if (r < L or R < l) return ; if (L ≤ l and r ≤ R) { t[k].cnt += type; if (type == 1) // them hcn nen bao phu ca canh t[k].len = (r-l+1); // chang han l = 5, r = #include #include #include #include #include #include using namespace std; typedef long long typedef int64_t typedef double ll; ll; real; // -// thi t[k].len = (5,6,7,8) else { // truong hop xoa thi phai lay thong tin tu node if (t[k].cnt == 0) t[k].len = t[k*2].len + t[k*2+1].len; } return ; } int mid = (l+r)/2; update(k*2,l,mid,L,R,type); update(k*2+1,mid+1,r,L,R,type); if (t[k].cnt == 0) t[k].len = t[k*2].len + t[k*2+1].len; } struct Node { int x, y1, y2, type; }; int main() { //freopen("INP.INP","r",stdin); struct Tree { //freopen("OUT.OUT","w",stdout); int len, cnt; scanf("%d", &n); }; for (int i=1;i≤n;i++) { int x1, y1, x2, y2; // -// scanf("%d%d%d%d", &x1,&y1,&x2,&y2); const int N = 30010; a[i].x = x1; int n, x0; // x0 la vi tri cuoi cung dang a[i+n].x = x2; xet a[i].y1 = a[i+n].y1 = y1; ll res; a[i].y2 = a[i+n].y2 = y2; Node a[N]; a[i].type = 1; Tree t[5*N]; // luu ve phuong dien a[i+n].type = -1; dai, khong phai toa (*) } // // n *= 2; sort(a+1,a+n+1,cmp); bool cmp(const Node u, const Node v) { //for (int i=1;i≤n;i++) return (u.x < v.x or (u.x == v.x and u.type // printf("%d %d %d %d\n", a[i].x, a[i].y1, < v.type)); a[i].y2, a[i].type); } for (int i=1;i≤n;i++) { //cout n xuất nghiệm ra, halt trước hết q = + Tạo biến L R lưu đoạn xét nói Khi ban đầu L = q R = q tăng R lên đến d1 thay đổi Xong xét đoạn L R tìm + Khởi tạo f[L] = Tạo f + Sau lấy giá trị cho f t (nhớ xét số điểm từ m, đoạn ban đầu findans) : điểm xét x Ta tìm đoạn mà r ≤ x để lấy ans đoạn mà x < l ( điểm thấp ) ta bỏ qua Trường hợp lại chia đoạn mà làm IT + Lấy giá trị xong cập nhật lại t: bỏ qua đoạn x không thuộc, tăng số lượng nút lên, l = r chia hai đoạn để it + q = R + Duyệt Code demo: #include #include bool compare(const ds u, const ds v) { 10 Sau cập nhật cho mảng F nút con, ta gán lại T[k]=0 để tránh trường hợp cộng lại nhiều lần Nếu đến đoạn nằm gọn đoạn x y ta tăng biến F[k], T[k*2], T[k*2+1] lên v Khi muốn lấy kết quả, ta làm QMAX, đến nút con, ta cần thực tăng giá trị T[k] cho T[k*2], T[k*2+1] F[k] để lấy kết Tức đến nút (trong thao tác nào, cập nhật hay lấy kết quả) Điều đảm bảo ta lấy giá trị xác, kiểu IT có thông tin truyền từ nút cha xuống nút Các bạn tham khảo chương trình để thấy rõ #include #include #include #include #include #include #include #include usingnamespace std; void solve0(){ scanf("%li%li%li",&L,&R,&v); update(1,1,n); } void solve1(){ scanf("%li%li",&L,&R); res = 0; findres(1,1,n); printf("%li\n",res); } const long maxn = 50000 + 100; long int main() n,m,L,R,loai,v,a[maxn],f[8*maxn],t[8*maxn],res { ; scanf("%li%li",&n,&m); /** for(long i=1;i≤m;i++){ t[k] la max cua doan nut k quan li scanf("%li",&loai); f[k] la mang phu luu phan can tang len cua if(loai == 0) solve0(); doan nut k else solve1(); quan li } **/ return0; void update(long k,long l,long r){ } t[k] += f[k]; f[k*2] += f[k]; f[k*2+1] += f[k]; f[k] = 0; if(r < L or R < l)return; if(L ≤ l and r ≤ R){ t[k] += v; f[k*2] += v; f[k*2+1] += v; return; } long m = (l+r)/2; update(k*2,l,m); update(k*2+1,m+1,r); t[k] = max(t[k*2],t[k*2+1]); } 13 void findres(long k,long l,long r){ t[k] += f[k]; f[k*2] += f[k]; f[k*2+1] += f[k]; f[k] = 0; if(r < L or R < l)return; if(L ≤ l and r ≤ R){ res = max(res,t[k]); return; } long m = (l+r)/2; findres(k*2,l,m); findres(k*2+1,m+1,r); } Bài http://vn.spoj.com/problems/NKLINEUP/ Hàng ngày lấy sữa, N bò bác John (1 ≤ N ≤ 50000) xếp hàng theo thứ tự không đổi Một hôm bác John định tổ chức trò chơi cho số bò Để đơn giản, bác John chọn đoạn liên tiếp bò để tham dự trò chơi Tuy nhiên để trò chơi diễn vui vẻ, bò phải không chênh lệch chiều cao Bác John chuẩn bị danh sách gồm Q (1 ≤ Q ≤ 200000) đoạn bò chiều cao chúng (trong phạm vi [1, 1000000]) Với đoạn, bác John muốn xác định chênh lệch chiều cao bò thấp cao Bạn giúp bác John thực công việc Dữ liệu • Dòng chứa số nguyên N Q • Dòng thứ i số N dòng sau chứa số nguyên nhất, độ cao bò thứ i • Dòng thứ i số Q chứa số nguyên A, B (1 ≤ A ≤ B ≤ N), cho biết đoạn bò từ A đến B Kết Gồm Q dòng, dòng chứa số nguyên, chênh lệch chiều cao bò thấp cao thuộc đoạn tương ứng Ví dụ Dữ liệu: 63 14 15 46 22 Kết qủa Thuật toán: Đây toán xử lí dãy số cần truy cập đến đoạn A B dãy, interval tree lựa chọn tốt Bài có điều may mắn không cần phải cập nhật lại chiều cao bò, thông tin interval tree cố định ta tạo interval tree dựa mảng chiều cao bò Mỗi đoạn ta cần in chênh lệch độ cao bò cao bò thấp nhất, cần tìm giá trị lớn giá trị nhỏ phần tử từ A đến B Ta dùng interval tree với nút lưu thông tin, giá trị lớn giá trị nhỏ đoạn mà biểu diễn, dùng interval tree, dùng để lưu giá trị lớn nhất, lại giá trị nhỏ Ở ta gọi maxt mint Khi muốn tìm kết dựa vào mảng Maxt để tìm GTLN đoạn A B, dùng mảng Mint để tìm GTNN đoạn A B, việc làm tương tự ví dụ viết giới thiệu Interval tree phía Chú ý tìm max hay tìm ta phải đến nút giống (do đến nút phụ thuộc A B) nên lần tìm cần gọi chung thủ tục #include #include int main() 15 #include { #include scanf("%li%li",&n,&q); #include for (long i=1;i≤n;i++) scanf("%li",&a[i]); using namespace std; update(1,1,n); const long maxn = 50000+100, maxh = for (long Q=1;Q≤q;Q++) { 1000000; scanf("%li%li",&L,&R); long hmax = 1; n,q,L,R,a[maxn],tmax[4*maxn],tmin[4*maxn],h hmin = maxh; max,hmin; findres(1,1,n); printf("%li\n",hmax-hmin); void update(long k,long l,long r) { } if (l == r) tmin[k] = tmax[k] = a[l]; return 0; else { } long m = (l+r)/2; update(k*2,l,m); update(k*2+1,m+1,r); tmax[k] = max(tmax[k*2],tmax[k*2+1]); tmin[k] = min(tmin[k*2],tmin[k*2+1]); } } void findres(long k,long l,long r) { if (not(r < L or R < l)) { if (L ≤ l and r ≤ R) { hmax = max(hmax,tmax[k]); hmin = min(hmin,tmin[k]); } else { long m = (l+r)/2; findres(k*2,l,m); findres(k*2+1,m+1,r); } } } Bài http://vn.spoj.com/problems/QMAX/ Cho dãy gồm n phần tử có giá trị ban đầu Cho m phép biến đổi, phép có dạng (u, v, k): tăng phần tử từ vị trí u đến vị trí v lên k đơn vị Cho q câu hỏi, câu có dạng (u, v): cho biết phần tử có giá trị lớn thuộc đoạn [u, v] Giới hạn • n, m, q ≤ 50000 • k>0 • Giá trị phần tử không vượt 231-1 16 Input • Dòng 1: n, m • m dòng tiếp theo, dòng chứa u, v, k cho biết phép biến đổi • Dòng thứ m+2: p • p dòng tiếp theo, dòng chứa u, v cho biết phép biến đổi Output • Gồm p dòng chứa kết tương ứng cho câu hỏi Example Input: 62 132 463 34 Output: Thuật toán: Bài ta có m phép biến đổi tăng dãy trước yêu cầu tìm giá trị lớn đoạn xen kẽ nhau, ta tìm cách xây dựng dãy số sau m phép biến đổi Khi có mảng giá trị sau m phép biến đổi, công việc lại ta tạo interval tree với nút lưu giá trị lớn đoạn mà quản lí phần tử mảng xác định, với mối truy vấn tìm GTLN ta làm không khó khăn Vấn đề xây dựng dãy số sau m phép biến đổi Ta sử dụng kĩ thuật đơn giản hiệu sau Giả sử mảng ta cần có mảng A[0 n+1], lúc đầu A[i]=0 với i Mỗi yêu cầu u,v,k tức tăng phần tử từ vị trí u đến vị trí v lên k đơn vị, ta làm sau: A[u]:=A[u]+k;A[v+1]:=A[v+1]-k; Sau đọc xong m phép biến đổi làm trên, cuối tính mảng A: For i:=1 to n 17 A[i]:=A[i]+A[i-1]; Các bạn tự chứng minh tính đắn hay viết đoạn chương trình kiểm nghiệm lại Như ta giải trọn vẹn toán #include void findres(long k,long l,long r) { #include if (not(r < L or R < l)) { #include if (L ≤ l and r ≤ R) #include res = max(res,t[k]); #include else { using namespace std; long m = (l+r)/2; const long maxn = 50000+100; findres(k*2,l,m); long n,m,k,u,v,q,L,R,a[maxn],t[4*maxn],res; findres(k*2+1,m+1,r); } void update(long k,long l,long r) { } if (l == r) t[k] = a[l]; } else { int main() long m = (l+r)/2; { update(k*2,l,m); scanf("%li%li",&n,&m); update(k*2+1,m+1,r); for (long i=1;i≤m;i++) { t[k] = max(t[k*2],t[k*2+1]); scanf("%li%li%li",&u,&v,&k); } a[u] += k; } a[v+1] -= k; } for (long i=1;i≤n;i++) a[i] += a[i-1]; update(1,1,n); scanf("%li",&q); for (long Q=1;Q≤q;Q++) { scanf("%li%li",&L,&R); res = 0; findres(1,1,n); printf("%li\n",res); } return 0;} Bài Dãy ngoặc http://laptrinh.ntu.edu.vn/Problem/Details/3270/?contestid=9 Khái niệm dãy ngoặc định nghĩa dạng đệ quy sau: () dãy ngoặc C dãy ngoặc C = (A) hay C = AB với A, B dãy ngoặc Ví dụ dãy ngoặc đúng: (), (()), ()(), (())() Ví dụ dãy ngoặc sai: )(, ((((, ()((, )))), )()( Cho trước dãy ngoặc gồm n dấu ngoặc đánh số từ đến n Có m câu hỏi, câu gồm hai số nguyên ≤ p ≤ r ≤ n, yêu cầu xác định xem dãy ngoặc 18 từ vị trí p đến vị trí r có phải dãy ngoặc hay không Hãy cho biết kết m câu hỏi Dữ liệu nhập: – Dòng hai số nguyên n, m cách khoảng trắng (1 ≤ n, m ≤ 105) – Dòng thứ hai dãy ngoặc ban đầu gồm n dấu ngoặc ‘(‘ hay ‘)’ – Trong m dòng tiếp theo, dòng thứ i hai số p i ri câu hỏi thứ i tương ứng, hai số cách khoảng trắng (1 ≤ pi ≤ ri ≤ n) Dữ liệu xuất: – Gồm m dòng ứng với m câu hỏi, dãy ngoặc tương ứng dãy ngoặc đúng, in YES, dãy ngoặc tương ứng dãy ngoặc đúng, in NO Ví dụ input • 85 (((()))) 14 36 48 45 27 output NO YES NO YES YES Thuật toán: #include using namespace std; int n, m, x, y, bb[400001], cc[400001]; char ch; bool check(int u, int v) { if ((v-u+1) & 1) return 0; int y = (u == ? : get(1, 1, n, u-1, u-1)); 19 void update(int k, int x, int y, int d, int c, int v) { if (c[...]... về chiều cao Bác John đã chuẩn bị một danh sách gồm Q (1 ≤ Q ≤ 200000) đoạn các con bò và chiều cao của chúng (trong phạm vi [1, 1000000]) Với mỗi đoạn, bác John muốn xác định chênh lệch chiều cao giữa con bò thấp nhất và cao nhất Bạn hãy giúp bác John thực hiện công việc này Dữ liệu • Dòng đầu tiên chứa 2 số nguyên N và Q • Dòng thứ i trong số N dòng sau chứa 1 số nguyên duy nhất, là độ cao của con... số nguyên, là chênh lệch chiều cao giữa con bò thấp nhất và cao nhất thuộc đoạn tương ứng Ví dụ Dữ liệu: 63 14 1 7 3 4 2 5 15 46 22 Kết qủa 6 3 0 Thuật toán: Đây là 1 bài toán xử lí trên dãy số và cần truy cập đến những đoạn A B bất kì trong dãy, vì vậy interval tree là 1 trong những lựa chọn tốt Bài này chúng ta có 1 điều may mắn là không cần phải cập nhật lại chiều cao của các con bò, vì vậy thông... hay không Hãy cho biết kết quả của m câu hỏi trên Dữ liệu nhập: – Dòng đầu tiên là hai số nguyên n, m cách nhau một khoảng trắng (1 ≤ n, m ≤ 105) – Dòng thứ hai là dãy ngoặc ban đầu gồm n dấu ngoặc ‘(‘ hay ‘)’ – Trong m dòng tiếp theo, tại dòng thứ i là hai số p i và ri của câu hỏi thứ i tương ứng, hai số cách nhau một khoảng trắng (1 ≤ pi ≤ ri ≤ n) Dữ liệu xuất: – Gồm m dòng ứng với m câu hỏi, nếu dãy... tự nào đó Lưu ý con búp bê i có thể đặt vào bên trong con búp bê j nếu (ai < aj) Dữ liệu vào: Dòng đầu tiên có 2 số N, M lần lượt là số lượng con búp bê của yenthanh132 và kích thước giới hạn của N con búp bê đó N luôn là số chẵn Dòng thứ 2 chứa N số ai, là kích thước của N con búp bê từ trái sang phải (1 ≤ ai ≤ M) Dữ liệu ra: Xuất ra số K theo yêu cầu của bài Nếu không có kết quả (không có cách sắp... lời đúng bằng cách xử lý danh sách và trả về các kết quả đúng Dữ liệu: * Dòng 1: Hai số nguyên cách nhau bởi khoảng trắng: N và M * Dòng 2 M+1: Mỗi dòng chứa một thao tác với ba số nguyên cách nhau bởi khoảng trắng: thao tác, S_i, và E_i Kết quả: * Dòng 1 số truy vấn: Với mỗi truy vấn, in ra kết quả là một số nguyên trên một dòng Ví dụ: Dữ liệu: 45 012 024 123 024 114 Kết quả: 23 1 2 Thuật toán: Ta có... may mắn là không cần phải cập nhật lại chiều cao của các con bò, vì vậy thông tin trong cây interval tree là cố định và ta sẽ tạo cây interval tree dựa trên mảng chiều cao của các con bò Mỗi đoạn thì ta cần in ra chênh lệch độ cao con bò cao nhất và con bò thấp nhất, vì vậy chúng ta cần tìm được giá trị lớn nhất và giá trị nhỏ nhất trong các phần tử từ A đến B Ta có thể dùng 1 cây interval tree với mỗi... bảng 24 - Ở mỗi lượt bắn, ktuan ghi lại tổng số ô mà các viên bi đã đi qua Bạn hãy viết chương trình mô phỏng lại trò chơi và với mỗi lượt bắn, in ra tổng số ô mà các viên bi của lượt bắn đó đã đi qua Dữ liệu - Dòng đầu ghi 3 số N, K, Q - K dòng sau, mỗi dòng ghi một cặp số (u,v) thể hiện toạ độ (dòng, cột) của một vật cản - Q dòng sau, mỗi dòng ghi 4 giá trị c, D, u, v Ký tự c có thể là 'L', 'R', 'T',... được đưa vào ðây phải là một ô nằm trên biên của bảng ứng với ký tự c D là số lượng viên bi sẽ bắn ở lượt chơi này Kết quả Với mỗi lượt chơi, in ra tổng số ô mà các viên bi của lượt đó đã đi qua Ví dụ Dữ liệu 513 33 L231 T111 B555 Kết quả 3 2 25 Giải thích Viên bi đầu tiên của lượt 1 sẽ đi qua 2 ô (3,1) và (3,2) trước ghi gặp vật cản ở ô (3,3) 25 Viên bi tiếp theo của lượt 1 sẽ đi qua ô (3,1) trước... học sinh sẽ chủ động hơn và sáng tạo cách giải quyết các bài tập gặp phải Và đây là cách tôi cho học sinh tiếp cận về Interval Tree Do năng lực bản thân còn hạn chế nên việc biên tập tài liệu này từ nhiều nguồn tài liệu khác nhau không tránh khỏi những thiếu sót Tôi rất mong được nhận được sự ủng hộ và góp ý thẳng thắn của người đọc về chuyên đề này Tôi chân thành cảm ơn! Người viết chuyên đề Đặng Tuấn

Ngày đăng: 02/06/2016, 21:54

Xem thêm: CẤU TRÚC dữ LIỆU NÂNG CAO

TỪ KHÓA LIÊN QUAN

Mục lục

    Thuật toán: Sử dụng Segment Tree

    Một nút lưu các giá trị :

    Cho 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 thuộc đoạn [u, v]

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

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w