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 e5f9576 commit 7f1ac27
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 21 deletions.
77 changes: 73 additions & 4 deletions 029.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 029 - Long Bricks (★5)

## 解答
## 解答 1

```cpp
#include <iostream>
Expand Down Expand Up @@ -42,6 +42,7 @@ public:

private:

// 伝搬
// ni: ノードのインデックス
void propagate(size_t ni)
{
Expand Down Expand Up @@ -86,7 +87,7 @@ private:
return;
}

// update(対象区間, value, 子ノード(左) のインデックス, 子ノード(左) の管理区間
// update(対象区間, value, 子ノード(左) のインデックス, 子ノード(左) の管理区間)
update(begin, end, value, (ni * 2 + 1), sBegin, (sBegin + sEnd) / 2);
// update(対象区間, value, 子ノード(右) のインデックス, 子ノード(右) の管理区間)
Expand Down Expand Up @@ -114,10 +115,10 @@ private:
return m_nodes[ni];
}

// rangeMax(対象区間, 子ノード(左) のインデックス, 子ノード(左) の管理区間);
// rangeMax(対象区間, 子ノード(左) のインデックス, 子ノード(左) の管理区間)
const int lc = rangeMax(begin, end, (ni * 2 + 1), sBegin, (sBegin + sEnd) / 2);
// rangeMax(対象区間, 子ノード(右) のインデックス, 子ノード(右) の管理区間);
// rangeMax(対象区間, 子ノード(右) のインデックス, 子ノード(右) の管理区間)
const int rc = rangeMax(begin, end, (ni * 2 + 2), (sBegin + sEnd) / 2, sEnd);
return std::max(lc, rc);
Expand Down Expand Up @@ -168,6 +169,74 @@ int main()
}
```
## 解答 2 (AC Library を使用)
自作の遅延評価セグメント木ではなく、AC Library に実装されている遅延評価セグメント木 [`atcoder::lazysegtree`](https://atcoder.github.io/ac-library/document_ja/lazysegtree.html) を使った解法です。
```cpp
#include <iostream>
#include <algorithm> // std::max()
#include <atcoder/lazysegtree.hpp> // atcoder::lazy_segtree
int Op(int a, int b)
{
return std::max(a, b);
}
int E()
{
return 0;
}
int Mapping(int f, int x)
{
return (f == 0 ? x : f);
}
int Composition(int f, int g)
{
return (f == 0 ? g : f);
}
int Id()
{
return 0;
}
int main()
{
// W 個の正方形のマス, N 個のレンガ
int W, N;
std::cin >> W >> N;
// 遅延評価セグメント木
atcoder::lazy_segtree<int, Op, E, int, Mapping, Composition, Id> segTree{ W };
// それぞれのレンガについて
for (int i = 0; i < N; ++i)
{
// 左から L 番目 ~ R 番目を覆う
int L, R;
std::cin >> L >> R;
// 区間をを [L, R) で表現する
// 1 番目 ~ 3 番目の場合 [0, 3)
--L;
// 対象区間の現在の高さ
const int oldH = segTree.prod(L, R);
// 対象区間の新しい高さ (+1)
const int newH = (oldH + 1);
// 対象区間の高さを更新する
segTree.apply(L, R, newH);
// 高さを出力
std::cout << newH << '\n';
}
}
```


## 部分点解答 (座標圧縮)
座標圧縮による解法で、小課題 1, 2 を解けます。
Expand Down
39 changes: 22 additions & 17 deletions 037.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public:

explicit RangeMaxQuery(size_t size)
{
// size 以上である 2 のべき乗数を求めて m_size に代入
// size 以上である 2 のべき乗数を求めて m_size に代入する
while (m_size < size)
{
m_size *= 2;
Expand All @@ -26,48 +26,53 @@ public:
m_nodes.resize((m_size * 2 - 1), std::numeric_limits<long long>::lowest());
}

// i 番目の要素を value に更新する
void update(size_t i, long long value)
{
// i をノードのインデックスにする
i += (m_size - 1);
// ノードのインデックス
size_t ni = (i + m_size - 1);

m_nodes[i] = value;
m_nodes[ni] = value;

// 親を更新していく
while (0 < i)
while (0 < ni)
{
// i を親のインデックスにする
i = (i - 1) / 2;
ni = (ni - 1) / 2;

// 親を更新
m_nodes[i] = std::max(m_nodes[(i * 2 + 1)], m_nodes[(i * 2 + 2)]);
m_nodes[ni] = std::max(m_nodes[(ni * 2 + 1)], m_nodes[(ni * 2 + 2)]);
}
}

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

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

// 確認するノードの区間が完全に含まれている場合
// 管理区間のすべてが対象区間に含まれていれば
if ((begin <= sBegin) && (sEnd <= end))
{
return m_nodes[si];
return m_nodes[ni];
}

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

// query(対象区間, 子ノード(右) のインデックス, 子ノード(右) の管理区間)
const long long m2 = query(begin, end, (ni * 2 + 2), (sBegin + sEnd) / 2, sEnd);
return std::max(m1, m2);
}

Expand Down Expand Up @@ -149,7 +154,7 @@ int main()
```

## 解答 2 (AC Library を使用)
自作セグメント木ではなく、AC Library に実装されているセグメント木 [`atcoder::segtree`](https://atcoder.github.io/ac-library/document_ja/segtree.html) を使った解法です。
自作のセグメント木ではなく、AC Library に実装されているセグメント木 [`atcoder::segtree`](https://atcoder.github.io/ac-library/document_ja/segtree.html) を使った解法です。

```cpp
#include <iostream>
Expand Down

0 comments on commit 7f1ac27

Please sign in to comment.