我々はすべて知っているように、キー・ルの約束は、有名な妖精の氷をだますことです。
トピック:https://www.luogu.org/problemnew/show/P1725
明らかに、DPは問題です(どうやら言葉は今あなたに嫌、嫌です)
状態遷移がDPである[I] = MAX(DP [K])+ [I]。
現在の位置が最大ジャンプは、現在位置の最大値が全ての位置の前方にジャンププラス凍結することができるです。
なぜ(それは偉大だったので)その両端キュー
これは、スライディングウィンドウを考えて、非常に裸となっています。T DPは、純粋な意志であるので、我々は、最大値を見つけるための時間を最適化します。
現在の値は、キューの値よりも大きい場合、キューは(私たちは前後を横断しているため、正面に位置し、小さな要素の値は、任意の寄付をすることはありません)ポップの要素を入れてきました。
コード
#include <cstdioを> する#include <CStringの> する#include <両端キュー> の#include <アルゴリズム> 使用して 名前空間STDを、 const int型 MAXN = 200100 ; 構造体ノード { int型のval; // DP最大值 のint NUM。// }; int型のn、[MAXN]、L、R。 int型DP [MAXN]。 両端キュー <ノード> S。 INT メイン() { scanf関数(" %D%D%D "、&N、&L&R)。 以下のための(int型私は=0 ; I <= N; I ++は) { scanfの(" %のD "、A + I); } int型の尾部は、= 0 ; DP [尾] = 0 ; ノードX; のため(int型 = L Iを、I <= N - 、I ++ )// Lへの遷移で0から始まる { 一方(s.size()&& DP [尾]> = s.back()ヴァル)。 { s.pop_back(); } // 無駄値ポップ x.num =尾; x.val = DP [尾]; s.push_back(X); // 新しい値を追加 IF(テールs.front()NUM> =(L-R&LTの+。1。))S.pop_front(); // キュー長 DP [I] = s.front()ヴァル+ A [i]の;. // この時点で、キューの先頭iが到達する最大正面ある 尾++を; } INT ANS = - MAXN; のため(int型 I = N - R&LTの+ 1 ; I <= N; I ++は) { ANS = MAX(ANS、DP [I]); } のprintf(" %のD " 、ANS); 戻り 0 。 }