atcoder/ac-library

Please help understanding: lazysegtree usage for range incremnents and range sums

ikr opened this issue · 2 comments

ikr commented

The following two tests fail for me:

#include "atcoder/lazysegtree.hpp"
#include "lest.hpp"
using namespace std;

constexpr int op(int x, int y) { return x + y; }
constexpr int e() { return 0; }

struct Calc final {
    void increment_range_inclusive(const int a, const int b) {
        lst.apply(a, b + 1, 1);
    }

    int sum_all() { return lst.all_prod(); }

    Calc() : lst(1'000'000) {}

  private:
    atcoder::lazy_segtree<int, op, e, int, op, op, e> lst;
};

// clang-format off
const lest::test tests[] = {
    CASE("Example 0") {
        Calc c{};
        c.increment_range_inclusive(1, 100);
        c.increment_range_inclusive(301, 400);
        c.increment_range_inclusive(101, 101);
        c.increment_range_inclusive(101, 102);
        c.increment_range_inclusive(1, 3);

        EXPECT(206 == c.sum_all());
    },
    CASE("Example 1") {
        Calc c{};
        c.increment_range_inclusive(1, 1);
        c.increment_range_inclusive(4, 4);
        c.increment_range_inclusive(51, 53);

        EXPECT(5 == c.sum_all());
    },
};
// clang-format on

int main(int argc, char **argv) { return lest::run(tests, argc, argv); }

Like that:

./solution.cpp:31: failed: Example 0: 206 == c.sum_all() for 206 == 20
./solution.cpp:39: failed: Example 1: 5 == c.sum_all() for 5 == 4
2 out of 2 selected tests failed.

Obviously, I misunderstand how to use atcoder::lazy_segtree for that kind of task. Could you please explain, what's the right way to increment ranges, and obtain the range sums then? Thank you!

Ah, btw, I did read the tutorial, and it even made sense :) but I'm still confused ¯\_(ツ)_/¯

( Probably this is not the place to ask how to use it, but here is the code that works for your reference).
Reference: https://betrue12.hateblo.jp/entry/2020/09/23/005940#%E5%8C%BA%E9%96%93%E5%8A%A0%E7%AE%97%E5%8C%BA%E9%96%93%E5%92%8C%E5%8F%96%E5%BE%97

#include "atcoder/lazysegtree.hpp"
using namespace std;

constexpr int op(int x, int y) { return x + y; }
constexpr int e() { return 0; }

struct S{
    int value;
    int size;
};
S S_op(S a, S b){ return {a.value+b.value, a.size+b.size}; }
S S_e(){ return {0, 1}; }

S mapping(int f, S x){
    return {x.value+x.size*f, x.size};
}

struct Calc final {
    void increment_range_inclusive(const int a, const int b) {
        lst.apply(a, b + 1, 1);
    }

    int sum_all() { return lst.all_prod().value; }

    Calc() : lst(1'000'000) {}

  private:
    atcoder::lazy_segtree<S, S_op, S_e, int, mapping, op, e> lst;
};

// clang-format off

template<typename T>
void EXPECT(T excect, T res) {
  cout << "excect:" << excect << ", res:" << res << (excect == res ? " OK" : " NG") << endl;
}

void test() {
    {
        Calc c{};
        c.increment_range_inclusive(1, 100);
        c.increment_range_inclusive(301, 400);
        c.increment_range_inclusive(101, 101);
        c.increment_range_inclusive(101, 102);
        c.increment_range_inclusive(1, 3);

        EXPECT(206, c.sum_all());
    }
    {
        Calc c{};
        c.increment_range_inclusive(1, 1);
        c.increment_range_inclusive(4, 4);
        c.increment_range_inclusive(51, 53);

        EXPECT(5, c.sum_all());
    }
};
// clang-format on

int main(int argc, char **argv) { 
  test();
}
ikr commented

@TumoiYorozu Awesome! Thanks a bunch!