From f7366924f269ad920144c944717a56b4a170c8bd Mon Sep 17 00:00:00 2001 From: Bruno Freitas Tissei <bft15@inf.ufpr.br> Date: Fri, 15 Feb 2019 16:12:12 -0200 Subject: [PATCH] Fix lazy seg tree Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br> --- algorithms/structure/lazy_segment_tree.cpp | 48 +++---- contests/Cadernaveis/URI1477.cpp | 148 +++++++++++++++++++++ 2 files changed, 172 insertions(+), 24 deletions(-) create mode 100644 contests/Cadernaveis/URI1477.cpp diff --git a/algorithms/structure/lazy_segment_tree.cpp b/algorithms/structure/lazy_segment_tree.cpp index 9f7552a..1fac1b0 100644 --- a/algorithms/structure/lazy_segment_tree.cpp +++ b/algorithms/structure/lazy_segment_tree.cpp @@ -10,9 +10,9 @@ int N, tree[4 * MAX], lazy[4 * MAX], v[MAX]; -// Build tree with elements from v -void build_tree(int node = 1, int a = 0, int b = N) { - if (a > b) +// Builds tree with elements from v +void build(int node = 1, int a = 0, int b = n) { + if (a > b) return; if (a == b) { @@ -20,14 +20,16 @@ void build_tree(int node = 1, int a = 0, int b = N) { return; } - build_tree(node * 2, a, (a + b) / 2); - build_tree(node * 2 + 1, 1 + (a + b) / 2, b); + build(node * 2, a, (a + b) / 2); + build(node * 2 + 1, (a + b) / 2 + 1, b); tree[node] = tree[node * 2] + tree[node * 2 + 1]; } -void push(int node, int val) { - tree[node] += value; +// Propagates value to tree and through lazy tree +void push(int node, int a, int b, int val) { + tree[node] += val; + // tree[node] += (b - a + 1) * val; (for Range Sum Query) if (a != b) { lazy[node * 2] += val; @@ -38,39 +40,37 @@ void push(int node, int val) { } -// Update segment [i,j] by adding value val -void update_tree(int i, int j, int val, int node = 1, int a = 0, int b = N) { +// Updates segment [i,j] by adding value val +void update(int i, int j, int val, int node = 1, int a = 0, int b = n) { if (lazy[node] != 0) - push(node, lazy[node]); + push(node, a, b, lazy[node]); - - if (a > b || a > j || b < i) + if (a > b or a > j or b < i) return; - if (a >= i && b <= j) { - push(node, val); + if (a >= i and b <= j) { + push(node, a, b, val); return; } - update_tree(i, j, node * 2, a, (a + b) / 2); - update_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b); + update(i, j, val, node * 2, a, (a + b) / 2); + update(i, j, val, node * 2 + 1, (a + b) / 2 + 1, b); tree[node] = tree[node * 2] + tree[node * 2 + 1]; } -// Return sum of [i,j] -int query_tree(int i, int j, int node = 1, int a = 0, int b = N) { +// Returns sum of [i,j] +int query(int i, int j, int node = 1, int a = 0, int b = n) { if (a > b || a > j || b < i) return 0; - if (lazy[node] != 0) { - push(node, val); - } + if (lazy[node]) + push(node, a, b, lazy[node]); - if (a >= i && b <= j) + if (a >= i and b <= j) return tree[node]; - int q1 = query_tree(i, j, node * 2, a, (a + b) / 2); - int q2 = query_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b); + int q1 = query(i, j, node * 2, a, (a + b) / 2); + int q2 = query(i, j, node * 2 + 1, (a + b) / 2 + 1, b); return q1 + q2; } diff --git a/contests/Cadernaveis/URI1477.cpp b/contests/Cadernaveis/URI1477.cpp new file mode 100644 index 0000000..3790a06 --- /dev/null +++ b/contests/Cadernaveis/URI1477.cpp @@ -0,0 +1,148 @@ +#include <bits/stdc++.h> + +#define MAX 101010 +#define EPS 1e-6 +#define MOD 1000000007 +#define inf 0x3f3f3f3f +#define llinf 0x3f3f3f3f3f3f3f3f + +#define fi first +#define se second +#define sz size() +#define pb push_back +#define ende '\n' + +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +#define mset(x, y) memset(&x, (y), sizeof(x)) + +using namespace std; + +typedef long long ll; +typedef pair<int,int> ii; + +typedef struct elem { + int h, e, r; + + elem() : h(0), e(0), r(0) {} + elem(int h, int e, int r) : h(h), e(e), r(r) {} + + elem operator+(const elem &x) { + return elem(h + x.h, e + x.e, r + x.r); + } + + void change(int n) { + int a = h, b = e, c = r; + if (n % 3 == 1) { + e = a; + r = b; + h = c; + } else if (n % 3 == 2) { + e = c; + r = a; + h = b; + } + } +} elem; + + +int n; +elem v[MAX]; +elem tree[MAX * 4]; +int lazy[MAX * 4]; + +void build(int node = 1, int a = 0, int b = n) { + if (a > b) return; + + if (a == b) { + tree[node] = v[a]; + return; + } + + build(node * 2, a, (a + b) / 2); + build(node * 2 + 1, (a + b) / 2 + 1, b); + tree[node] = tree[node * 2] + tree[node * 2 + 1]; +} + + +void push(int node, int a, int b, int val) { + tree[node].change(val); + + if (a != b) { + lazy[node * 2] += val; + lazy[node * 2 + 1] += val; + } + + lazy[node] = 0; +} + + +void update(int i, int j, int node = 1, int a = 0, int b = n) { + if (lazy[node] != 0) + push(node, a, b, lazy[node]); + + if (a > b or a > j or b < i) + return; + + if (a >= i and b <= j) { + push(node, a, b, 1); + return; + } + + update(i, j, node * 2, a, (a + b) / 2); + update(i, j, node * 2 + 1, (a + b) / 2 + 1, b); + tree[node] = tree[node * 2] + tree[node * 2 + 1]; +} + + +elem query(int i, int j, int node = 1, int a = 0, int b = n) { + if (a > b || a > j || b < i) + return elem(); + + if (lazy[node]) + push(node, a, b, lazy[node]); + + if (a >= i and b <= j) + return tree[node]; + + elem q1 = query(i, j, node * 2, a, (a + b) / 2); + elem q2 = query(i, j, node * 2 + 1, (a + b) / 2 + 1, b); + return q1 + q2; +} + + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + int m; + while (cin >> n >> m) { + for (int i = 0; i < MAX * 4; ++i) { + tree[i] = elem(); + lazy[i] = 0; + } + + for (int i = 0; i < n; ++i) { + v[i].h = 1; + v[i].e = v[i].r = 0; + } + + build(); + + for (int i = 0; i < m; ++i) { + char op; + int a, b; cin >> op >> a >> b; + + if (op == 'C') { + elem x = query(a - 1, b - 1); + cout << x.h << " " << x.e << " " << x.r << ende; + } else { + update(a - 1, b - 1); + } + } + + cout << ende; + } + + return 0; +} -- GitLab