目次- DAY 5 モノトーンキュー/スタック
- トレーニング概要
- A問題
- B問題
- C問題
- D問題
- E問題 未解決、解説補完
- F問題 未解決、解説補完
- G問題 CFデータでWAのヒントを得る
- J問題
- K問題
- L問題
- 補足情報
- モノトーンスタック
-
- モノトーンスタック
- 矩形関連
- 辞書順最小
- 貢献度法
- モノトーンキュー
DAY 5 モノトーンキュー/スタック
トレーニングリンク:リンク
トレーニング概要
- 2023.6.30 午前:A、B、C、D問題 午後:E問題(未公開、解説参照)F問題(現在のアプローチ不明) 夜:牛客小白月賽75+F、G問題 今日の学習は主にモノトーンスタック関連の問題に集中。他のキュー系問題は既に解いており、後ほど補完予定
- 2023.7.1 午前:J、K、L問題 7.1午前は1時間かけてモノトーンキューの復習と整理 他の問題は時間の都合で後回し
A問題
問題概要: 数列が与えられ、各要素の次の大きな値のインデックスを特定する。見つからない場合は0を出力 アプローチ: 降順モノトーンスタックのテンプレート問題
B問題
問題概要: 牛の高さの配列が与えられ、各牛が自分より高い牛を見つけるまでの間の牛の数を合計する アプローチ: A問題と同様の降順モノトーンスタックだが、問題文の解釈がやや複雑
C問題
問題概要: 長さnの配列から[l, r]の区間を選択し、その区間内の最大値と第二最大値のXORの最大値を求める アプローチ: 降順モノトーンスタックを活用して区間の最大値・第二最大値を効率的に特定。スタック操作時にXOR値を更新することでO(n)計算量を実現。この手法はO(n^3)の全探索に比べて圧倒的に高速
D問題
問題概要: すべての区間[l, r]で最大値が和以上であることを確認する アプローチ: 降順スタックで最大値を管理し、スタック操作時に最大値と和の比較を行う。ここでのポイントは、スタックの左右境界に注目することで、すべての区間を網羅的に検証できる点。これは、スタックの構造が区間の性質を保証するためである
E問題 未解決、解説補完
問題概要: すべての区間の第二最大値の総和を求める アプローチ: 単純なモノトーンスタックでは第二最大値の検出が困難。洛谷の解説ではスタックに加えてST表を使用する方法が紹介されている。この実装は今後の学習課題
/*
難易度:高
ロジックは洛谷の解説に基づく。現在理解中
双方向リストの構造を活用したアプローチ
*/
const int maxm=1e5+5,inf=0x3f3f3f3f,mod=998244353;
ll n,a[maxm],L[maxm],R[maxm];
void process(){
cin>>n;
ll t;
for(int i=1;i<=n;++i){
cin>>t;
//数値の位置を記録
a[t]=i;
//初期の左右境界を設定
L[i]=i-1;
R[i]=i+1;
}
ll ans=0;
for(int i=1;i<=n;++i){//昇順で処理
//左右の境界を取得
int l=L[a[i]],r=R[a[i]];
//左側の区間処理
if(l>=1) ans+=i*(l-L[l])*(r-a[i]);
//右側の区間処理
if(r<=n) ans+=i*(R[r]-r)*(a[i]-l);
//現在の要素を削除
L[r]=l;R[l]=r;
}
cout<<ans<<'\n';
return ;
}
関連資料: Second Sum! - Acfboy のブログ - 洛谷ブログ (luogu.com.cn)
F問題 未解決、解説補完
問題概要: 制約付き配列構築問題。V字型パターンを避ける アプローチ: モノトーンスタックで非増加/非減少列を検出。中央凸型のケースを考慮するため、前後缀和を活用
/*
WAの可能性あり
問題文の解釈が不正確だった可能性
*/
const int maxm=5e5+5,inf=0x3f3f3f3f,mod=998244353;
ll n,nums[maxm],left[maxm],right[maxm],ans[maxm];
ll prefix[maxm],suffix[maxm];
void process(){
cin>>n;
for(int i=1,j;i<=n;++i){
cin>>nums[i];
//スタック構造で境界を検出
j=i-1;
while(j>0 && nums[i]<nums[j]){
j=left[j];
}
left[i]=j;
//前缀和の計算
prefix[i]=prefix[j]+1ll*(i-j)*nums[i];
}
ll s=0,t;
for(int i=n,j;i>0;--i){
//スタック構造で境界を検出
j=i+1;
while(j<=n && nums[i]<nums[j]) j=right[j];
right[i]=j;
//後缀和の計算
suffix[i]=suffix[j]+1ll*(j-i)*nums[i];
//最適解の更新
if(prefix[i]+suffix[i]-nums[i]>s){
s=prefix[i]+suffix[i]-nums[i];
t=i;
}
}
//最適解の構築
for(int i=t-1;i>0;--i){
if(nums[i]>nums[i+1]) nums[i]=nums[i+1];
}
for(int i=t+1;i<=n;++i){
if(nums[i]>nums[i-1]) nums[i]=nums[i-1];
}
for(int i=1;i<=n;++i){
cout<<nums[i]<<" \n"[i==n];
}
return ;
}
関連資料: 解説リンク
G問題 CFデータでWAのヒントを得る
問題概要: n個の数列において、特定の条件を満たす移動経路の最短手数を求める アプローチ: モノトーンスタックを活用して移動条件の検証。重複値の取り扱いに注意
J問題
問題概要: モノトーンキューのテンプレート問題 アプローチ: 降順/昇順キューの維持で解決
K問題
問題概要: モノトーンキューのテンプレート問題 アプローチ: 誤解によりWA。区間最小値の検出に昇順キューを使用
L問題
問題概要: モノトーンキューのテンプレート問題 アプローチ: 昇順キューで最小値を維持
補足情報
モノトーンスタック Monotone Stack
【図解】スタックの2つのアプローチ https://leetcode.cn/problems/next-greater-node-in-linked-list/solution/tu-jie-dan-diao-zhan-liang-chong-fang-fa-v9ab/ 例:各要素の左右で厳密に大きい要素の位置を返す 理解のポイント:配列を山脈に見立て、スタックの性質を活用 テクニック:スタックの底に境界要素を事前に追加して処理を簡略化 変換ルール: 区間[l,r]の最大値がa[r]の場合、l > left[r]が成立 区間[l,r]の最大値がa[l]の場合、r < right[l]が成立
https://oi-wiki.org/ds/monotonous-stack/ https://cp-algorithms.com/data_structures/stack_queue_modification.html
モノトーンスタック
-
- 次の大きい要素 I(スタックテンプレート)
-
- 次の大きい要素 II
-
- 次の大きい要素 IV
-
- 132パターン
-
- 毎日温度
-
- 株価のスパン
-
- リンクドリストの次の大きい要素
-
- 良い期間
-
- 商品割引後の価格
-
- 非減少順に並べる
矩形関連
-
- 柱状図の最大矩形
-
- 最大矩形
-
- 全1サブマトリクスのカウント
辞書順最小
-
- 重複文字を削除
- 316拡張:重複回数制限
-
- K文字を削除
-
- 最大数を構成
貢献度法
-
- 子配列の最小値和
-
- 子配列最小積の最大
-
- 子配列の範囲和
-
- 魔術師の総力和 テンプレート問題 https://www.luogu.com.cn/problem/P5788 https://www.luogu.com.cn/problem/P2866 http://poj.org/problem?id=3250 NEERC05,UVa 1619 https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=825&page=show_problem&problem=4494 変換 https://codeforces.com/problemset/problem/280/B 変換 LC2289 https://leetcode.cn/problems/steps-to-make-array-non-decreasing/ max >= sum https://codeforces.com/problemset/problem/1691/D LC1124 https://leetcode.cn/problems/longest-well-performing-interval/ スタックの考え方 LC1944 https://leetcode.cn/problems/number-of-visible-people-in-a-queue/ 次の大きい要素 LC2454 https://leetcode.cn/problems/next-greater-element-iv/
- 応用 https://atcoder.jp/contests/abc140/tasks/abc140_e 最小値*サブ配列和 LC1856 https://leetcode.cn/problems/maximum-subarray-min-product/ 辞書順最小 LC316 https://leetcode.cn/problems/remove-duplicate-letters/
- 拡張:重複回数制限 https://leetcode.cn/contest/tianchi2022/problems/ev2bru/ LC402 https://leetcode.cn/problems/remove-k-digits/ LC321 https://leetcode.cn/problems/create-maximum-number/ 貢献度の計算(すべてのサブ配列の...和) 最小値 LC907 https://leetcode.cn/problems/sum-of-subarray-minimums/ 最大値-最小値 LC2104 https://leetcode.cn/problems/sum-of-subarray-ranges/ 最小値*和 LC2281 https://leetcode.cn/problems/sum-of-total-strength-of-wizards/ 第二位 LC1504 https://leetcode-cn.com/problems/count-submatrices-with-all-ones/ DPと組み合わせ https://codeforces.com/problemset/problem/5/E https://codeforces.com/problemset/problem/1313/C2 https://codeforces.com/problemset/problem/1407/D 線分木と組み合わせて最適値を維持 https://codeforces.com/problemset/problem/1483/C 最大値に基づく分類 LC1335 https://leetcode.cn/problems/minimum-difficulty-of-a-job-schedule/ LC2355 https://leetcode.cn/problems/maximum-number-of-books-you-can-take/ その他 LC42 雨水の収集 https://leetcode-cn.com/problems/trapping-rain-water/ 評価:3種類の解法(DP、スタック、双指針)を解説 LC84 柱状図の最大矩形 https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ http://poj.org/problem?id=2559 http://poj.org/problem?id=2082 LC85 全1矩形(実装は下記のmaximalRectangleArea)https://leetcode-cn.com/problems/maximal-rectangle/ 原問題は http://poj.org/problem?id=3494 LC1504 全1矩形数(実装は下記のnumSubmat)https://leetcode-cn.com/problems/count-submatrices-with-all-ones/ LC768 https://leetcode.cn/problems/max-chunks-to-make-sorted-ii/ 末尾配列+異なる矩形の数の合計 https://codeforces.com/edu/course/2/lesson/2/5/practice/contest/269656/problem/D bitOpTrickCntと組み合わせ(見つけるbits.go)https://codeforces.com/problemset/problem/875/D 一部のrightから全体のrightを復元;rightからaを復元 https://codeforces.com/problemset/problem/1158/C
モノトーンキュー Monotone Queue
2つの図で理解するキュー(Python/Java/C++/Go) https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/solution/liang-zhang-tu-miao-dong-dan-diao-dui-li-9fvh/ キューの単調性を維持し、常に最大/最小値を保つ 前提知識:双指針 固定サイズの窓の最大値を例に: 左端を1つずつ移動する際、キューの先頭が左端の場合、最大値が変化するためキューの先頭を削除 これにより、常にキューの先頭が現在の窓の最大値となる https://oi-wiki.org/ds/monotonous-queue/ https://oi-wiki.org/dp/opt/monotonous-queue-stack/ https://cp-algorithms.com/data_structures/stack_queue_modification.html https://blog.csdn.net/weixin_43914593/article/details/105791217 競技プログラミング专题解析(13):DP最適化(3)--モノトーンキュー最適化 todo https://xyzl.blog.luogu.org/DQ-OP-DP
- トライアル問題 59-II. キューの最大値(キューテンプレート)
-
- スライディングウィンドウ最大値
-
- 和がK以上の最短サブアレイ
-
- 絶対差が制限内の最長連続サブアレイ https://leetcode.cn/tag/monotonic-queue/problemset/ モノトーンキューによるDP最適化 todo https://www.luogu.com.cn/problem/P2627 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1070 マウスの洞窟 http://codeforces.com/problemset/problem/797/F LC375 数字を当てるII https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/ https://leetcode.cn/problems/guess-number-higher-or-lower-ii/solution/cong-ji-yi-hua-sou-suo-on3-dao-dong-tai-q13g9/