Skip to content

Commit

Permalink
QQ
Browse files Browse the repository at this point in the history
  • Loading branch information
fffelix-huang committed Jul 24, 2023
1 parent ff361e8 commit 5b6c6fb
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 113 deletions.
8 changes: 4 additions & 4 deletions library/data-structure/lazy-segtree.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once
#include <vector>
#include <algorithm>
#include <functional>
#include <cassert>
#include "segtree.hpp"

Expand All @@ -16,9 +18,7 @@ struct lazy_segtree : public segtree<S, e, op> {
using base = segtree<S, e, op>;

public:
using base::all_prod;

lazy_segtree() : lazy_segtree(0) {}
lazy_segtree() {}
explicit lazy_segtree(int _n) : lazy_segtree(std::vector<S>(_n, e())) {}
explicit lazy_segtree(const std::vector<S>& v) : base(v), lz(size, id()) {}

Expand Down Expand Up @@ -145,4 +145,4 @@ struct lazy_segtree : public segtree<S, e, op> {
}
};

} // namespace felix
} // namespace felix
36 changes: 36 additions & 0 deletions library/data-structure/range-add-range-sum.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once
#include "fenwick.hpp"

namespace felix {

template<class T>
struct range_add_range_sum {
public:
range_add_range_sum() {}
explicit range_add_range_sum(int _n) : f0(_n), f1(_n) {}

void add(int p, T x) { add(p, p + 1, x); }

// [l, r)
void add(int l, int r, T x) {
f0.add(l, x);
f1.add(l, -l * x);
f0.add(r, -x);
f1.add(r, r * x);
}

T get(int p) const { return sum(p, p + 1); }

// [l, r)
T sum(int l, int r) const {
T res = 0;
res += f0.get(r) * r + f1.get(r);
res -= f0.get(l) * l + f1.get(l);
return res;
}

private:
fenwick<T> f0, f1;
};

} // namespace felix
219 changes: 110 additions & 109 deletions library/data-structure/segtree.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include <vector>
#include <algorithm>
#include <functional>
#include <cassert>

Expand All @@ -8,124 +9,124 @@ namespace felix {
template<class S, S (*e)(), S (*op)(S, S)>
struct segtree {
public:
segtree() : segtree(0) {}
explicit segtree(int _n) : segtree(std::vector<S>(_n, e())) {}
explicit segtree(const std::vector<S>& a): n(a.size()) {
log = std::__lg(2 * n - 1);
size = 1 << log;
d.resize(size * 2, e());
for(int i = 0; i < n; ++i) {
d[size + i] = a[i];
}
for(int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S val) {
assert(0 <= p && p < n);
p += size;
d[p] = val;
for(int i = 1; i <= log; ++i) {
update(p >> i);
}
}
segtree() {}
explicit segtree(int _n) : segtree(std::vector<S>(_n, e())) {}
explicit segtree(const std::vector<S>& a): n(a.size()) {
log = std::__lg(2 * n - 1);
size = 1 << log;
d.resize(size * 2, e());
for(int i = 0; i < n; ++i) {
d[size + i] = a[i];
}
for(int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S val) {
assert(0 <= p && p < n);
p += size;
d[p] = val;
for(int i = 1; i <= log; ++i) {
update(p >> i);
}
}

S get(int p) const {
assert(0 <= p && p < n);
return d[p + size];
}
S get(int p) const {
assert(0 <= p && p < n);
return d[p + size];
}

S operator[](int p) const { return get(p); }
S prod(int l, int r) const {
assert(0 <= l && l <= r && r <= n);
S sml = e(), smr = e();
for(l += size, r += size; l < r; l >>= 1, r >>= 1) {
if(l & 1) {
sml = op(sml, d[l++]);
}
if(r & 1) {
smr = op(d[--r], smr);
}
}
return op(sml, smr);
}
S operator[](int p) const { return get(p); }
S prod(int l, int r) const {
assert(0 <= l && l <= r && r <= n);
S sml = e(), smr = e();
for(l += size, r += size; l < r; l >>= 1, r >>= 1) {
if(l & 1) {
sml = op(sml, d[l++]);
}
if(r & 1) {
smr = op(d[--r], smr);
}
}
return op(sml, smr);
}

S all_prod() const { return d[1]; }
S all_prod() const { return d[1]; }

template<bool (*f)(S)> int max_right(int l) {
return max_right(l, [](S x) { return f(x); });
}
template<bool (*f)(S)> int max_right(int l) {
return max_right(l, [](S x) { return f(x); });
}

template<class F> int max_right(int l, F f) {
assert(0 <= l && l <= n);
assert(f(e()));
if(l == n) {
return n;
}
l += size;
S sm = e();
do {
while(~l & 1) {
l >>= 1;
}
if(!f(op(sm, d[l]))) {
while(l < size) {
push(l);
l <<= 1;
if(f(op(sm, d[l]))) {
sm = op(sm, d[l++]);
}
}
return l - size;
}
sm = op(sm, d[l++]);
} while((l & -l) != l);
return n;
}
template<class F> int max_right(int l, F f) {
assert(0 <= l && l <= n);
assert(f(e()));
if(l == n) {
return n;
}
l += size;
S sm = e();
do {
while(~l & 1) {
l >>= 1;
}
if(!f(op(sm, d[l]))) {
while(l < size) {
push(l);
l <<= 1;
if(f(op(sm, d[l]))) {
sm = op(sm, d[l++]);
}
}
return l - size;
}
sm = op(sm, d[l++]);
} while((l & -l) != l);
return n;
}

template<bool (*f)(S)> int min_left(int r) {
return min_left(r, [](S x) { return f(x); });
}
template<bool (*f)(S)> int min_left(int r) {
return min_left(r, [](S x) { return f(x); });
}

template<class F> int min_left(int r, F f) {
assert(0 <= r && r <= n);
assert(f(e()));
if(r == 0) {
return 0;
}
r += size;
S sm = e();
do {
r--;
while(r > 1 && (r & 1)) {
r >>= 1;
}
if(!f(op(d[r], sm))) {
while(r < size) {
push(r);
r = 2 * r + 1;
if(f(op(d[r], sm))) {
sm = op(d[r--], sm);
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while((r & -r) != r);
return 0;
}
template<class F> int min_left(int r, F f) {
assert(0 <= r && r <= n);
assert(f(e()));
if(r == 0) {
return 0;
}
r += size;
S sm = e();
do {
r--;
while(r > 1 && (r & 1)) {
r >>= 1;
}
if(!f(op(d[r], sm))) {
while(r < size) {
push(r);
r = 2 * r + 1;
if(f(op(d[r], sm))) {
sm = op(d[r--], sm);
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while((r & -r) != r);
return 0;
}
protected:
int n, size, log;
std::vector<S> d;
int n, size, log;
std::vector<S> d;

void update(int v) {
d[v] = op(d[2 * v], d[2 * v + 1]);
}
void update(int v) {
d[v] = op(d[2 * v], d[2 * v + 1]);
}

virtual void push(int p) {}
virtual void push(int p) {}
};

} // namespace felix
} // namespace felix

0 comments on commit 5b6c6fb

Please sign in to comment.