単調なキュー、つまりコンパレーターに関連する内部要素の順序付けされたキューは、シーケンスの連続した間隔で最大値/最小値を簡単にクエリできます
また、状態遷移時の決定を最適化して、時間の複雑さを軽減することもできます。(まあ、この文章はOI-Wikiで言われています。konjacqwqはdpを最適化する方法がわからないからです)
たとえば、長さnの数列の連続する各k数の最小数を知りたいとします。
激しく解く場合、トラバーサルは1からn-k + 1、複雑度O(n * k)であり、各サブシーケンスの値は、比較的遅い他の値と比較する必要があります。
この問題では、減少する単調なキューを維持し、キュー内の数値範囲がkを超えないように注意することができます
メンテナンス方法:
新しい番号がシーケンスで読み取られるたびに、その番号とチームの最後の番号との関係が比較されます
1.番号がチームの最後の番号より大きい場合は、チームに参加します。
2.サマリーがチームの終わりよりも小さい場合、チームの終わりはチームの外にあり、その数はチームの終わりと再度比較されます。
チームに入った後、現在のチームの先頭と末尾の番号に含まれる番号範囲がkを超えているかどうかを確認します
超過した場合、チームは初めてチームを離れます。
cin >> t; while(!dq.empty()&& dq.back()> t) dq.pop_back()、no.pop_back(); dq.push_back(t)、no.push_back(i); while(no.back()-no.front()> = k) dq.pop_front()、no.pop_front();
//これは、dequeをコンテナーメンテナンスの単調なキューとして使用しています。また、dequeもありません。dq内の番号の対応する番号(添え字)を維持します
この方法で維持されるキューの先頭要素は、常にすべてのk要素の最小です
O(1)を取り出すことができ、各番号は最大で1回デキューおよびエンキューできます。キューを維持する時間の複雑さはO(n)のみです。