Skip to content

Commit

Permalink
Update 037.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Reputeless committed May 4, 2022
1 parent e273c9c commit 059ab00
Showing 1 changed file with 40 additions and 22 deletions.
62 changes: 40 additions & 22 deletions 037.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
#include <limits> // std::numeric_limits<>::lowest()

// セグメント木による Range Maximum Query
class RangeMaxQuery
class SegmentTree
{
public:

RangeMaxQuery() = default;
SegmentTree() = default;

explicit RangeMaxQuery(size_t size)
// ツリーの初期化(単位元は std::numeric_limits<long long>::lowest())
explicit SegmentTree(size_t size)
{
// size 以上である 2 のべき乗数を求めて m_size に代入する
while (m_size < size)
Expand All @@ -26,8 +27,22 @@ public:
m_nodes.resize((m_size * 2 - 1), std::numeric_limits<long long>::lowest());
}

// i 番目の要素を value に更新する
void update(size_t i, long long value)
// 値の初期化
void init(const std::vector<long long>& values)
{
for (size_t i = 0; i < values.size(); ++i)
{
m_nodes[m_size - 1 + i] = values[i];
}

for (int i = static_cast<int>(m_size) - 2; i >= 0; --i)
{
update(i);
}
}

// 一点更新
void set(size_t i, long long value)
{
// ノードのインデックス
size_t ni = (i + m_size - 1);
Expand All @@ -45,35 +60,41 @@ public:
}
}

// クエリ対象区間 [begin, end) における最大値を求める
// 区間クエリ(対象区間 [begin, end) における最大値を求める
long long query(size_t begin, size_t end) const
{
return query(begin, end, 0, 0, m_size);
}

private:

// クエリ対象区間 [begin, end) における最大値を求める.
// ni: 確認するノードのインデックス. そのノードの管理区間は [sBegin, sEnd)
long long query(size_t begin, size_t end, size_t ni, size_t sBegin, size_t sEnd) const
// ノードの更新
void update(size_t ni)
{
m_nodes[ni] = std::max(m_nodes[(ni * 2 + 1)], m_nodes[(ni * 2 + 2)]);
}

// 区間クエリ(対象区間 [begin, end) における最大値を求める)
// ni: 確認するノードのインデックス. そのノードの管理区間は [nBegin, nEnd)
long long query(size_t begin, size_t end, size_t ni, size_t nBegin, size_t nEnd) const
{
// クエリ対象区間が管理区間と無関係なら
if ((sEnd <= begin) || (end <= sBegin))
if ((nEnd <= begin) || (end <= nBegin))
{
return std::numeric_limits<long long>::lowest();
}

// 管理区間のすべてがクエリ対象区間に含まれていれば
if ((begin <= sBegin) && (sEnd <= end))
if ((begin <= nBegin) && (nEnd <= end))
{
return m_nodes[ni];
}

// query(クエリ対象区間, 子ノード(左) のインデックス, 子ノード(左) の管理区間)
const long long m1 = query(begin, end, (ni * 2 + 1), sBegin, (sBegin + sEnd) / 2);
const long long m1 = query(begin, end, (ni * 2 + 1), nBegin, (nBegin + nEnd) / 2);

// query(クエリ対象区間, 子ノード(右) のインデックス, 子ノード(右) の管理区間)
const long long m2 = query(begin, end, (ni * 2 + 2), (sBegin + sEnd) / 2, sEnd);
const long long m2 = query(begin, end, (ni * 2 + 2), (nBegin + nEnd) / 2, nEnd);

return std::max(m1, m2);
}
Expand Down Expand Up @@ -114,8 +135,8 @@ int main()
std::vector<std::vector<long long>> dp(N + 1, std::vector<long long>(W + 1, -1));
dp[0][0] = 0;

std::vector<RangeMaxQuery> rmqs(N + 1, RangeMaxQuery(W + 1));
rmqs[0].update(0, 0);
std::vector<SegmentTree> rmqs(N + 1, SegmentTree(W + 1));
rmqs[0].set(0, 0);

for (int i = 1; i <= N; ++i) // i 個目の料理を見る
{
Expand Down Expand Up @@ -157,7 +178,7 @@ int main()
// セグメント木を更新
for (int k = 0; k <= W; ++k)
{
rmqs[i].update(k, dp[i][k]);
rmqs[i].set(k, dp[i][k]);
}
}

Expand Down Expand Up @@ -187,7 +208,7 @@ long long E()
}
// セグメント木による Range Maximum Query
using RangeMaxQuery = atcoder::segtree<long long, Op, E>;
using SegmentTree = atcoder::segtree<long long, Op, E>;
// 料理を表す構造体
struct Dish
Expand Down Expand Up @@ -220,7 +241,7 @@ int main()
std::vector<std::vector<long long>> dp(N + 1, std::vector<long long>(W + 1, -1));
dp[0][0] = 0;
std::vector<RangeMaxQuery> rmqs(N + 1, RangeMaxQuery(W + 1));
std::vector<SegmentTree> rmqs(N + 1, SegmentTree(W + 1));
rmqs[0].set(0, 0);
for (int i = 1; i <= N; ++i) // i 個目の料理を見る
Expand Down Expand Up @@ -261,10 +282,7 @@ int main()
}
// セグメント木を更新
for (int k = 0; k <= W; ++k)
{
rmqs[i].set(k, dp[i][k]);
}
rmqs[i] = SegmentTree(dp[i]);
}
// 解答 (dp[N][W]) を出力
Expand Down

0 comments on commit 059ab00

Please sign in to comment.