From 49eeb6695f680cc490e701b33b8590d1aceea160 Mon Sep 17 00:00:00 2001 From: 3agwa Date: Mon, 14 Oct 2019 20:06:51 +0200 Subject: [PATCH 1/2] added hashing segment tree code --- .../Segment Tree/Hashing Segment Tree.cpp | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Data Structures/Segment Tree/Hashing Segment Tree.cpp diff --git a/Data Structures/Segment Tree/Hashing Segment Tree.cpp b/Data Structures/Segment Tree/Hashing Segment Tree.cpp new file mode 100644 index 00000000..c705c862 --- /dev/null +++ b/Data Structures/Segment Tree/Hashing Segment Tree.cpp @@ -0,0 +1,111 @@ +// Hashing Segment Tree +/* + * we'll maintain a rolling hash array, so pw[0] = 1, pw[i] = base*pw[i-1]%mod + * we'll also maintain the sum of bases so far, we'll use this to find our hash value when using lazy propagation + * the idea is this: our pw[] array will have the values 1, 10, 100, 1000.. and so on + * therefore, if we want an entire range to have the same lazy value (let's say 9) and our range is 4 + * then, the hashed value would be 9999, this is equivalent to 1111*9, we get the 1111 value by accumulation of array pw[] + * when we're merging two ranges, we'll multiply the one on the left by the length of the right range then add them up + * hence, we have tree[node] = left*pw[en-mid] + right + * finally, suppose we are updating a range with length = 2, we should get the sum[en-st] and not en-st+1 + * this is because we include the value 1 as our first hash/sum, so we don't have to use the range inclusive + */ + +const int N = 1e5 + 5, mod = 1e9 + 9, base = 10; + +ll tree[4 * N], lazy[4 * N], pw[4 * N], sum[4 * N]; + +void propagate(int node, int st, int en) +{ + if (~lazy[node]) + { + tree[node] = (sum[en - st] * 1ll * lazy[node]) % mod; + if (st != en) + lazy[2 * node] = lazy[2 * node + 1] = lazy[node]; + lazy[node] = -1; + } +} + +void update(int node, int st, int en, int shemal, int yemeen, int val) +{ + propagate(node, st, en); + + if (st > en || st > yemeen || en < shemal) + return; + + if (shemal <= st && en <= yemeen) + { + lazy[node] = val; + propagate(node, st, en); + return; + } + + int mid = (st + en) / 2; + + update(2 * node, st, mid, shemal, yemeen, val); + update(2 * node + 1, mid + 1, en, shemal, yemeen, val); + + int a = tree[2 * node], b = tree[2 * node + 1]; + + tree[node] = ((a * 1ll * pw[en - mid] % mod) + b) % mod; +} + +void query(int node, int st, int en, int shemal, int yemeen, ll &ans) +{ + propagate(node, st, en); + + if (st > en || st > yemeen || en < shemal) + return; + + if (shemal <= st && en <= yemeen) + { + ans = ((ans * 1ll * pw[en - st + 1]) % mod + tree[node]) % mod; + return; + } + + int mid = (st + en) / 2; + + query(2 * node, st, mid, shemal, yemeen, ans); + query(2 * node + 1, mid + 1, en, shemal, yemeen, ans); +} + +int main() +{ + pw[0] = sum[0] = 1; + rep(i, 1, 4 * N) + pw[i] = (base * pw[i - 1]) % mod, sum[i] = (sum[i - 1] + pw[i]) % mod; + + reset(lazy, -1); + + int n, m, k; + cin >> n >> m >> k; + string x; + cin >> x; + x.insert(x.begin(), '0'); + + erep(i, 1, n) + update(1, 1, n, i, i, x[i] - '0'); + int q = m + k; + while (q--) + { + int t, l, r, c; + cin >> t >> l >> r >> c; + if (t == 1) + update(1, 1, n, l, r, c); + else + { + ll a = 0; + query(1, 1, n, l, r - c, a); + ll b = 0; + query(1, 1, n, l + c, r, b); + + if (a == b) + cout << "YES\n"; + else + cout << "NO\n"; + } + } + + return 0; +} + From 296a33c8aa9c65265d4f9423739ebebf728f61a9 Mon Sep 17 00:00:00 2001 From: 3agwa Date: Mon, 14 Oct 2019 20:11:48 +0200 Subject: [PATCH 2/2] adadded code for persistent segment tree --- .../Segment Tree/Persistent Segment Tree.cpp | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Data Structures/Segment Tree/Persistent Segment Tree.cpp diff --git a/Data Structures/Segment Tree/Persistent Segment Tree.cpp b/Data Structures/Segment Tree/Persistent Segment Tree.cpp new file mode 100644 index 00000000..2f6583ae --- /dev/null +++ b/Data Structures/Segment Tree/Persistent Segment Tree.cpp @@ -0,0 +1,51 @@ +// Persistent Segment Tree +const int N = 100000 + 5; + +struct node +{ + int l, r, cnt; + + node() + { + l = r = 0; + cnt = 0; + } +} tree[20 * N]; // each persistent version holds a range inside this tree, maximum nodes created is NlogN + +int arr[N], sz, root[N]; // N persistent versions +vi vec; + +void update(int &curr, int prev, int st, int en, int idx) +{ + curr = ++sz; // gives id to the current node + tree[curr] = tree[prev]; // new node has the same values as the old node + if (st == en) + { + tree[curr].cnt++; + return; + } + + int mid = (st + en) / 2; + + if (idx <= mid) // move towards the target + update(tree[curr].l, tree[prev].l, st, mid, idx); + else + update(tree[curr].r, tree[curr].r, mid + 1, en, idx); + + tree[curr].cnt = tree[tree[curr].l].cnt + tree[tree[curr].r].cnt; +} + +int query(int curr, int prev, int st, int en, int idx) +{ + if (st == en) + return st; + int cnt = tree[tree[curr].l].cnt - tree[tree[prev].l].cnt; + int mid = (st + en) / 2; + if (idx <= cnt) + return query(tree[curr].l, tree[prev].l, st, mid, idx); + return query(tree[curr].r, tree[prev].r, mid + 1, en, idx - cnt); +} + +update(root[1], 0, 1, s, arr[1]); +erep(i, 2, n) +update(root[i], root[i - 1], 1, s, arr[i]);