Nyaan's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: segment-tree/segment-tree-max-of-interval.hpp

Verified with

Code

#pragma once

#include <algorithm>
using namespace std;

// セグ木用のモノイド (区間更新用のコンストラクタもある)
//
// sum : 全体の sum
// max, lmax, rmax : (連続部分列の要素の和)の max (空の区間を認めない)
// min, lmin, rmin : (連続部分列の要素の和)の min (空の区間を認めない)
// num : 区間の長さ
template <typename T>
struct MaxInterval {
  T sum, max, lmax, rmax, min, lmin, rmin;
  long long num;
  MaxInterval()
      : sum(0), max(0), lmax(0), rmax(0), min(0), lmin(0), rmin(0), num(0) {}
  // [x] 1 個からなる区間
  MaxInterval(T x)
      : sum(x), max(x), lmax(x), rmax(x), min(x), lmin(x), rmin(x), num(1) {}
  // [x] num 個からなる区間
  MaxInterval(T x, long long _num) {
    if (_num == 0) {
      sum = max = lmax = rmax = min = lmin = rmin = num = 0;
    } else {
      sum = x * _num;
      max = lmax = rmax = (x > 0 ? x * _num : x);
      min = lmin = rmin = (x < 0 ? x * _num : x);
      num = _num;
    }
  }
  bool operator==(const MaxInterval& rhs) const {
    return sum == rhs.sum && max == rhs.max && lmax == rhs.lmax &&
           rmax == rhs.rmax && min == rhs.min && lmin == rhs.lmin &&
           rmin == rhs.rmin && num == rhs.num;
  }
  bool operator!=(const MaxInterval& rhs) const { return !(*this == rhs); }

  // 区間のマージ
  friend MaxInterval merge(const MaxInterval& a, const MaxInterval& b) {
    if (a == MaxInterval{}) return b;
    if (b == MaxInterval{}) return a;
    MaxInterval c;
    c.sum = a.sum + b.sum;
    c.max = ::max({a.max, b.max, a.rmax + b.lmax});
    c.lmax = ::max(a.lmax, a.sum + b.lmax);
    c.rmax = ::max(b.rmax, b.sum + a.rmax);
    c.min = ::min({a.min, b.min, a.rmin + b.lmin});
    c.lmin = ::min(a.lmin, a.sum + b.lmin);
    c.rmin = ::min(b.rmin, b.sum + a.rmin);
    c.num = a.num + b.num;
    return c;
  }
};
#line 2 "segment-tree/segment-tree-max-of-interval.hpp"

#include <algorithm>
using namespace std;

// セグ木用のモノイド (区間更新用のコンストラクタもある)
//
// sum : 全体の sum
// max, lmax, rmax : (連続部分列の要素の和)の max (空の区間を認めない)
// min, lmin, rmin : (連続部分列の要素の和)の min (空の区間を認めない)
// num : 区間の長さ
template <typename T>
struct MaxInterval {
  T sum, max, lmax, rmax, min, lmin, rmin;
  long long num;
  MaxInterval()
      : sum(0), max(0), lmax(0), rmax(0), min(0), lmin(0), rmin(0), num(0) {}
  // [x] 1 個からなる区間
  MaxInterval(T x)
      : sum(x), max(x), lmax(x), rmax(x), min(x), lmin(x), rmin(x), num(1) {}
  // [x] num 個からなる区間
  MaxInterval(T x, long long _num) {
    if (_num == 0) {
      sum = max = lmax = rmax = min = lmin = rmin = num = 0;
    } else {
      sum = x * _num;
      max = lmax = rmax = (x > 0 ? x * _num : x);
      min = lmin = rmin = (x < 0 ? x * _num : x);
      num = _num;
    }
  }
  bool operator==(const MaxInterval& rhs) const {
    return sum == rhs.sum && max == rhs.max && lmax == rhs.lmax &&
           rmax == rhs.rmax && min == rhs.min && lmin == rhs.lmin &&
           rmin == rhs.rmin && num == rhs.num;
  }
  bool operator!=(const MaxInterval& rhs) const { return !(*this == rhs); }

  // 区間のマージ
  friend MaxInterval merge(const MaxInterval& a, const MaxInterval& b) {
    if (a == MaxInterval{}) return b;
    if (b == MaxInterval{}) return a;
    MaxInterval c;
    c.sum = a.sum + b.sum;
    c.max = ::max({a.max, b.max, a.rmax + b.lmax});
    c.lmax = ::max(a.lmax, a.sum + b.lmax);
    c.rmax = ::max(b.rmax, b.sum + a.rmax);
    c.min = ::min({a.min, b.min, a.rmin + b.lmin});
    c.lmin = ::min(a.lmin, a.sum + b.lmin);
    c.rmin = ::min(b.rmin, b.sum + a.rmin);
    c.num = a.num + b.num;
    return c;
  }
};
Back to top page