63
Data Structure - Tree

Datastructure tree

  • Upload
    rantd

  • View
    198

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Datastructure tree

Data Structure - Tree

Page 2: Datastructure tree

Binary Index Tree

Problem:

Give an array A[1], A[2] , … , A[n] and m queries as follows (n, m ~ 10^6)

type 1: add x to A[k] (1 <= k <= n)

type 2: calculate sum of interval [l , r] of array

Page 3: Datastructure tree

Binary Index Tree

Naive solution

type 1: O(1)

type 2: O(n)

→ time complexity O(mn)

m, n ~ 10^6 → impossible

Page 4: Datastructure tree

Binary Index Tree

• Fenwick Tree (also called BIT)

• Peter M. Fenwick, "A New Data Structure for Cumulative Frequency Tables" (1994)

• Support fast operations on array

Page 5: Datastructure tree

Binary Index Tree

Support two operations in O(log(n))

[1] Add value x to an element A[k]

A[k] → A[k] + x

[2] Return sum of prefix k

prefix[k] = A[1] + A[2] + ... + A[k]

Page 6: Datastructure tree

Binary Index Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

Page 7: Datastructure tree

Binary Index Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

add to A[1]

Page 8: Datastructure tree

Binary Index Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

add to A[3]

Page 9: Datastructure tree

Binary Index Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

get prefix[3]

Page 10: Datastructure tree

Binary Index Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

get prefix[7]

Page 11: Datastructure tree

Binary Index Tree

• Observation

Express k as binary number

1→1 2→10 3→11 4→100

5→101 6→110 7→111 8→1000

Pay attention to number of ‘0’ at the end

add operation : k → k + (last bit 1 of k)

get operation: k → k – (last bit 1 of k)

Page 12: Datastructure tree

Binary Index Tree

[1] Add value to element at position index

void add(int index, int value) {

for (int i = index; i <= size; i += i & -i) {

bit[index] += value;

}

} → O(log(n))

Page 13: Datastructure tree

Binary Index Tree

[1] Get sum of elements from postion 1 -> index

int get(int index) {

int ans = 0;

for (int i = index; i > 0; i -= i & -i) {

ans += bit[i];

}

return ans;

} → O(log(n))

Page 14: Datastructure tree

Binary Index Tree

• Total time complexity for m queries

Naive: O(mn) → BIT: O(mlog(n))

Amazing 🎉 Bravo 👏

Let see some practical uses of BIT

Page 15: Datastructure tree

Count Inverse Pair

Give an array A[1], A[2], ..., A[n], n ~ 10^6

Count number of pair (A[i], A[j]) such that

i < j and A[i] > A[j]

Naive solution: scan all pairs (A[i], A[j]) , i < j

→ time complexity O(n^2) → impossible

Page 16: Datastructure tree

Another solution

• Using technique of merge sort

Divide and conquer (A[1], ... ,A[n])

→ (A[1], ... ,A[n/2]) ∨ (A[n/2+1], ..., A[n])

solve(A[1], ... ,A[n/2])

solve(A[n/2+1], ..., A[n])

merge(A[1], ... ,A[n/2] ∨A[n/2+1], ..., A[n])

Time complexity O(nlog(n))

Page 17: Datastructure tree

Using BIT

Suppose 1 <= A[1], A[2], ..., A[n] <= n and are integer.

If not, we can make a mapping by sort because we only consider about magnitude correlation

ex: (1.2, -9.8, 5.0, 3.4) → (2, 1, 4, 3)

Page 18: Datastructure tree

Using BIT

int ans = 0;

void solve() {

for (int i = 1; i <= n; ++i) {

ans += i - 1 - get(a[i]);

add(a[i], 1);

}

}

Page 19: Datastructure tree

D-Query

Problem:

Given an array n number A[1], A[2], ..., A[n] and m queries as follows (n ~ 3x10^4, m ~ 2x10^5, 1 <= A[i] <= 10^6)

query : (l, r) return number of distinct elements in subarray A[l], A[l+1], ..., A[r]

→ Cann’t solve with naive solution

Page 20: Datastructure tree

D-Query

Solution with BIT

[1] Sort queries based on right value

(l1,r1), (l2,r2), ..., (lm, rm)

→ r1 <= r2 <= ... <= rm

[2] Go through array from left to right, using index[] to save last position each value

→ index[x] is last position of x in current array

Page 21: Datastructure tree

D-Query

Solution with BIT

[3] Current value a[i]

*if index[a[i]] != i then update index[a[i]] = i

*if there is some r[j] = i then calculate answer and go to next queries

*else go to next postion

[4] Print answers

Page 22: Datastructure tree

D-Query

struct queries {

int l, r, id;

};

bool comp(queries x, queries y) {

return x.r < y.r;

}

sort(queries.begin(), queries.end(), comp);

Page 23: Datastructure tree

D-Query

for (int j = 0, i = 1; j < num_queries;) {

if (index[a[i]] != i) {

bit.add(index[a[i]], -1);

index[a[i]] = i;

bit.add(i, 1);

}

if (queries[j].r == i) {

ans[queries[j].id] += bit.get(i) – bit.get(queries[j].l – 1);

j++;

}

else i++;

}

Page 24: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

index[1] = -1index[2] = -1index[3] = -1

3 queries[2, 4][1, 5][3, 5]

Page 25: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

3 queries[2, 4][1, 5][3, 5]

index[1] = 1→ bit.add(-1, -1) , bit.add(1, 1)index[2] = -1index[3] = -1

Page 26: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

3 queries[2, 4][1, 5][3, 5]

index[1] = 2→ bit.add(1, -1) , bit.add(2, 1)index[2] = -1index[3] = -1

Page 27: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

3 queries[2, 4][1, 5][3, 5]

index[1] = 2index[2] = 3→ bit.add(-1, -1) , bit.add(3, 1)index[3] = -1

Page 28: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

3 queries[2, 4][1, 5][3, 5]

index[1] = 4→ bit.add(2, -1) , bit.add(4, 1)→ ans[2] = bit.get(4) – bit.get(1)index[2] = 3index[3] = -1

Page 29: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

3 queries[2, 4][1, 5][3, 5]

index[1] = 4index[2] = 3index[3] = 5→ bit.add(-1, -1) , bit.add(5, 1)→ ans[1] = bit.get(5) – bit.get(0)

Page 30: Datastructure tree

D-Query

1 1 2 1 3

3 queries[1, 5][2, 4][3, 5]

3 queries[2, 4][1, 5][3, 5]

index[1] = 4index[2] = 3index[3] = 5→ ans[3] = bit.get(5) – bit.get(2)

Page 31: Datastructure tree

Segment Tree

Problem:

Give an array A[1], A[2], ..., A[n] and m queries as follows (n, m ~ 10^6)

type 1: add x to A[k]

type 2: calculate max, min on interval [l, r]

Page 32: Datastructure tree

Segment Tree

Naive solution

Same as previous one

type 1: O(1)

type 2: O(n)

→ time complexity O(mn)

→ impossible when n, m ~ 10^6

Page 33: Datastructure tree

Segment Tree

• Discoverd by Bentley in 1977 in “Solution to Klee’s rectangle problems”

• Support fast operations on interval

Page 34: Datastructure tree

Segment Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

Page 35: Datastructure tree

Segment Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

add to A[2]

Page 36: Datastructure tree

Segment Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

add to A[6]

Page 37: Datastructure tree

Segment Tree

A[1] + A[2] + A[3] + A[4] A[5] + A[6] + A[7] + A[8]

A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

A[1] + A[2] A[3] + A[4] A[5] + A[6] A[7] + A[8]

A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

get max on [3,8]

Page 38: Datastructure tree

Segment Tree

• Each node of tree is an interval [l, r]

• If l < r, it has two children [l, m] and [m+1, r] with m = (l + r)/2

• Length of array is n → total node of tree is

1 + 2 + 4 + ... + 2^k = 2^(k+1) – 1

k is smallest number such that 2^k >= n

→ total node <= 4n, memory O(n)

Page 39: Datastructure tree

Segment Tree

(1 , 4) (5 , 8)

(1 , 8)

(1 , 2) (3 , 4) (5 , 6) (7 , 8)

(1 , 1) (2 , 2) (3 , 3) (4 , 4) (5 , 5) (6 , 6) (7 , 7) (8 , 8)

1

2 3

4 5 6 7

8 9 10 11 12 13 14 15

Page 40: Datastructure tree

Segment Tree

*Initialize: build(1, 1, n)

void build(int node, int l, int r) {

if (l == r) {sg[node] = A[l]; return;}

int m = (l + r)/2;

build(node * 2, l, m);

build(node * 2 + 1, m + 1, r);

sg[node] = max(sg[node * 2], sg[node * 2 + 1]);

} → O(n)

Page 41: Datastructure tree

Segment Tree

*Add x to A[k]: update(1, 1, n, k, x)

void update(int node, int l, int r, int k, int x) {

if (l == r) {sg[node] = A[k] + x; return;}

int m = (l + r)/2;

if (m >= k) update(node * 2, l, m, k, x);

else update(node * 2 + 1, m + 1, r, k, x);

sg[node] = max(sg[node * 2], sg[node * 2 + 1]);

} → O(log(n))

Page 42: Datastructure tree

Segment Tree

*Get max on interval [l,r]: query(1, 1, n, l, r)

int query(int node, int i, int j, int l, int r) {

if (l<=i && j <= r) {return sg[node];}

int m = (i + j)/2;

if (m >= r) return query(node * 2, i, m, l, r);

else if (m < l) return query(node * 2 + 1, m + 1, j, l, r);

else return max(query(node * 2, i, m, l, r), query(node * 2 + 1, m + 1, j, l, r));

} → O(log(n))

Page 43: Datastructure tree

Treap

• What is treap?

• Combination of tree and heap → treap

• Height of tree is proportional to log(n) with high probability (n is number of keys in tree)

• Each node has two attributes: key and priority number

• Key is binary-tree ordered, priority number is heap ordered

Page 44: Datastructure tree

Treap

• Support search, insertion, deletion, merge and split

• When insert a key, priority number is randomed → time complexity of all operations are expected O(log(n))

Page 45: Datastructure tree

Treap

50100

6750

2519

1233

6073

2087

keypri

Page 46: Datastructure tree

Treap

typedef struct node {

int val, pri, cnt, sum;

struct node * child[2];

node(int v, int p) : val(v), pri(p), cnt(1), sum(v) {

child[0] = child[1] = NULL;

}

} * node_t;

Page 47: Datastructure tree

Treap

int count(node_t t) {

return t ? t->cnt : 0;

}

int sum(node_t t) {

return t ? t->sum : 0;

}

node_t update(node_t t) {

t->cnt = count(t->child[0]) + count(t->child[1]) + 1;

t->sum = sum(t->child[0]) + sum(t->child[1]) + t->val;

return t;

}

Page 48: Datastructure tree

Insertion

• Randomize a priority number

• Insert node to tree as binary search tree

• Rotate tree until priority number is heap-ordered

• Expected time complexity: O(log(n))

Page 49: Datastructure tree

Insertion

50100

6750

2519

1233

6073

2087

55150

Page 50: Datastructure tree

Insertion

50100

6750

2519

1233

6073

2087

55150

Page 51: Datastructure tree

Insertion

50100

6750

2519

1233

6073

2087

55150

Page 52: Datastructure tree

Rotation

node_t rotate(node_t t, int b) {

node_t s = t->child[b];

t->child[1-b] = s->child[b];

s->child[b] = t;

update(t);

update(s);

return s;

}

Page 53: Datastructure tree

Rotation

Q

CP

BA

P

A Q

CB

Page 54: Datastructure tree

Deletion

• Find node as binary search tree

• Bring node to leaf and delete

• Rotate tree until priority number is heap-ordered

• Expected time complexity: O(log(n))

Page 55: Datastructure tree

Deletion

50100

6750

2519

1233

6073

2087

55150

Page 56: Datastructure tree

Deletion

50100

6750

2519

1233

6073

2087

55150

Page 57: Datastructure tree

Deletion

50100

6750

2519

1233

6073

55150

Page 58: Datastructure tree

Deletion

50100

6750

2519

1233

6073

55150

Page 59: Datastructure tree

Merge-Split

• Merge two treaps into one

• Split treap into two treaps

• Implement indirectly by insertion and deletion

• Implement directly

• Expected time complexity: O(log(n))

Page 60: Datastructure tree

Merge

A B C D

a b

Page 61: Datastructure tree

Merge

A B

C D

a

b

Page 62: Datastructure tree

Merge

node_t merge(node_t l, node_t r) {if (!l || !r) return !l ? r : l;if (l->pri > r->pri) {

l->child[1] = merge(l->child[1], r);return update(l);

}else {

r->child[0] = merge(l, r->child[0]);return update(r);

}}

Page 63: Datastructure tree

Merge → Insert

T

valpri

merge(treap T, node x)