Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Reputeless committed May 1, 2022
1 parent d3a48e4 commit e5f9576
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 41 deletions.
94 changes: 54 additions & 40 deletions 029.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public:

explicit LazySegmentTree(size_t size)
{
// size 以上である 2 のべき乗数を求めて m_size に代入
// size 以上である 2 のべき乗数を求めて m_size に代入する
while (m_size < size)
{
m_size *= 2;
Expand All @@ -26,97 +26,111 @@ public:
m_lazyNodes.resize((m_size * 2 - 1), 0);
}

// 区間 [begin, end) を value に更新する.
// 対象区間 [begin, end) を value に更新する
void update(size_t begin, size_t end, int value)
{
// update(対象区間, value, 0, 全区間);
update(begin, end, value, 0, 0, m_size);
}

// 区間 [begin, end) における最大値を求める
// 対象区間 [begin, end) における最大値を求める
int rangeMax(size_t begin, size_t end)
{
// rangeMax(対象区間, 0, 全区間);
return rangeMax(begin, end, 0, 0, m_size);
}

private:

// si: ノードのインデックス
void propagate(size_t si)
// ni: ノードのインデックス
void propagate(size_t ni)
{
if (m_lazyNodes[si])
// 現在のノードに遅延評価の値があれば
if (m_lazyNodes[ni])
{
m_nodes[si] = m_lazyNodes[si];
// 現在のノードの計算済みの値に反映する
m_nodes[ni] = m_lazyNodes[ni];

// 最下段でなければ子ノードに伝搬
if (si < (m_size - 1))
// 最下段でなければ子ノードに遅延評価の値を伝搬する
if (ni < (m_size - 1))
{
m_lazyNodes[si * 2 + 1] = std::max(m_lazyNodes[si * 2 + 1], m_lazyNodes[si]);
m_lazyNodes[si * 2 + 2] = std::max(m_lazyNodes[si * 2 + 2], m_lazyNodes[si]);
m_lazyNodes[ni * 2 + 1] = std::max(m_lazyNodes[ni * 2 + 1], m_lazyNodes[ni]);
m_lazyNodes[ni * 2 + 2] = std::max(m_lazyNodes[ni * 2 + 2], m_lazyNodes[ni]);
}

m_lazyNodes[si] = 0;
// 現在のノードの遅延評価の値を空にする
m_lazyNodes[ni] = 0;
}
}

// 区間 [begin, end) を value に更新する.
// si: 確認するノードのインデックス. そのノードに対応する区間は [sBegin, sEnd)
void update(size_t begin, size_t end, int value, size_t si, size_t sBegin, size_t sEnd)
// 対象区間 [begin, end) を value に更新する.
// ni: 確認するノードのインデックス. そのノードの管理区間は [sBegin, sEnd)
void update(size_t begin, size_t end, int value, size_t ni, size_t sBegin, size_t sEnd)
{
propagate(si);

// 更新するノードの区間と交差しない場合
// 対象区間が管理区間と無関係なら
if ((sEnd <= begin) || (end <= sBegin))
{
return;
return; // 何もしない
}
// 更新するノードの区間が完全に含まれている場合

propagate(ni);

// 管理区間のすべてが対象区間に含まれていれば
if ((begin <= sBegin) && (sEnd <= end))
{
m_lazyNodes[si] = value;
propagate(si);
// 現在のノードの遅延評価の値に value をセット
m_lazyNodes[ni] = value;
propagate(ni);
return;
}

update(begin, end, value, (si * 2 + 1), sBegin, (sBegin + sEnd) / 2);
update(begin, end, value, (si * 2 + 2), (sBegin + sEnd) / 2, sEnd);
// update(対象区間, value, 子ノード(左) のインデックス, 子ノード(左) の管理区間
update(begin, end, value, (ni * 2 + 1), sBegin, (sBegin + sEnd) / 2);
// update(対象区間, value, 子ノード(右) のインデックス, 子ノード(右) の管理区間)
update(begin, end, value, (ni * 2 + 2), (sBegin + sEnd) / 2, sEnd);
m_nodes[si] = std::max(m_nodes[si * 2 + 1], m_nodes[si * 2 + 2]);
// 現在のノードの計算済みの値を、子ノード (左, 右) の計算済みの値をもとに更新
m_nodes[ni] = std::max(m_nodes[ni * 2 + 1], m_nodes[ni * 2 + 2]);
}

// 区間 [begin, end) における最大値を求める.
// si: 確認するノードのインデックス. そのノードに対応する区間は [sBegin, sEnd)
int rangeMax(size_t begin, size_t end, size_t si, size_t sBegin, size_t sEnd)
// 対象区間 [begin, end) における最大値を求める.
// ni: 確認するノードのインデックス. そのノードの管理区間は [sBegin, sEnd)
int rangeMax(size_t begin, size_t end, size_t ni, size_t sBegin, size_t sEnd)
{
propagate(si);

// 確認するノードの区間と交差しない場合
// 対象区間が管理区間と無関係なら
if ((sEnd <= begin) || (end <= sBegin))
{
return 0;
return 0; // 空の値を返す
}

// 確認するノードの区間が完全に含まれている場合
propagate(ni);

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

const int lc = rangeMax(begin, end, (si * 2 + 1), sBegin, (sBegin + sEnd) / 2);
const int rc = rangeMax(begin, end, (si * 2 + 2), (sBegin + sEnd) / 2, sEnd);
// rangeMax(対象区間, 子ノード(左) のインデックス, 子ノード(左) の管理区間);
const int lc = rangeMax(begin, end, (ni * 2 + 1), sBegin, (sBegin + sEnd) / 2);
// rangeMax(対象区間, 子ノード(右) のインデックス, 子ノード(右) の管理区間);
const int rc = rangeMax(begin, end, (ni * 2 + 2), (sBegin + sEnd) / 2, sEnd);
return std::max(lc, rc);
}

private:

size_t m_size = 1;

// 計算済みの配列
// 計算済みの値の配列
std::vector<int> m_nodes;

// 遅延評価用の配列
// 遅延評価の値の配列
std::vector<int> m_lazyNodes;
};

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ C++17 標準ライブラリの機能を優先して使い、競技プログラ
|006| | | | |
|013| | | | |
|021| | | | |
|[029](https://atcoder.jp/contests/typical90/tasks/typical90_ac)|[Long Bricks](./029.md)|★5|(1) [👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/029-01.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-01.cpp)[📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-02.cpp)<br>(2) [👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/029-02.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-03.cpp)|(解法 1) 「座標圧縮」で効率化<br>(解法 2) 区間に対する処理は「セグメント木」|
|[029](https://atcoder.jp/contests/typical90/tasks/typical90_ac)|[Long Bricks](./029.md)|★5|(1) [👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/029-01.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-01.cpp),[📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-02.cpp)<br>(2) [👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/029-02.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-03.cpp)|(解法 1) 「座標圧縮」で効率化<br>(解法 2) 区間に対する処理は「セグメント木」|
|030| | | | |
|036| | | | |
|[037](https://atcoder.jp/contests/typical90/tasks/typical90_ak)|[Don't Leave the Spice](./037.md)|★5|[👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/037.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/037.cpp)|DP をセグメント木で高速化|
Expand Down

0 comments on commit e5f9576

Please sign in to comment.