質問の意味:あなたの順序を与えるために、あなたは接頭辞のシーケンスを選択することができ、インターバルと可能な限り小さく、最大k個の部品を必要とするk個の連続セクション、への接頭辞は、この最小値が最大値である尋ねますか?
アイデア:まず、MIN MAXは簡単に2を考える参照してください。2つの中間値のそれぞれについて、我々は、元の配列かどうかを決定し、以下のK間隔の中間部を構成することができる、これはDPで行うことができます。まずプレフィックス間隔と減算形になることがプレフィックス系列とを決定しました。その後、現在のプレフィクス和[I]は、我々は接頭辞および以上和[I]見つける - 中間状態のもので、その転送にDPの最大値。K以上での存在下での最後の状態のDP値ならば、ミッド値が上限を減らすために、大きすぎる二部説明しました。そして、その逆。DP +セグメント離散最適化木、Oの全体的な複雑さ(N * LOGN)*ログ(範囲)
コード:
#include <ビット/ STDC ++ H> に#define LL長い長い (<< 1 O)の#define LS の#define RS(1 << O | 1) 名前空間stdを使用。 const int型MAXN = 200010; LL和[MAXN]。 LL [MAXN]。 LL [MAXN】b。 INT DP [MAXN]、MX [MAXN * 4]。 N INT、M、TOT。 ボイドビルド(int型、L、O INT、INT R){ IF(L == R){ MX [O] = -1。 返します。 } INT半ば=(L + R)>> 1。 (LS、L、ミッド)を構築。 (RS、ミッド+ 1、r)を構築します。 MX [O] = MAX(MX [LS]、MX [RS])。 } ボイド更新(int型、L、O INT、INT R、INT P、INTヴァル){ IF(L == R){ MX [O] = MAX(MX [O]、ヴァル)。 返します。 } INT半ば=(L + R)>> 1。 IF(p <= MID)更新(LS、L、中、P、ヴァル)。 他の更新(RS、ミッド+ 1、R、P、val)で、 MX [O] = MAX(MX [LS]、MX [RS])。 } INTクエリ(INT O、int型のL、R INT、INT QL、QR INT){ IF(QL> QR)リターン-1。 IF(L> = QL && R <= QR){ 戻りMX [O]。 } INT半ば=(L + R)>> 1、ANS = -1。 IF(QL <= MID)ANS = MAX(ANS、クエリ(LS、L、中間、QL、QR))。 IF(QR> MID)ANS = MAX(ANS、クエリ(RS、ミッド+ 1、R、QL、QR))。 ANSを返します。 } {(LLミッド)を解くBOOL (1、1、TOT)を構築します。 アップデート(1、1、TOT、LOWER_BOUND(B + 1、B + 1回の+ TOT、0) - B、0); 以下のために{(INT i = 1; iが++; iが<= N) INT P = LOWER_BOUND(B + 1、B + 1 + TOT、和[I] - MID) - B。 INT P1 = LOWER_BOUND(B + 1、B + 1 + TOT、和[I]) - B。 INT TMP =クエリ(1、1、TOT、P、TOT)。 IF(TMP == -1)DP [I] = -1。 他のDP [i]は、TMP + = 1; IF(DP [I]> = M)戻り0; アップデート(1、1、TOT、P1、DP [I])。 } 1を返します。 } int型のmain(){ int型のT。 // freopenは( "INPUT.TXT"、 "R"、STDIN)。 // freopenは( "1.in"、 "R"、STDIN)。 scanf関数( "%のD"、&T)。 (T--){一方 のscanf( "%d個の%のD"、&N、&M)。 以下のために(INT i = 1; iが<= N; iが++){ scanf関数( "%のLLDを" &[I])。 和[I] =和[I - 1] + [I]。 B [I] =和[I]。 } B [N + 1] = 0; ソート(B + 1、B + 1 + N + 1)。 LL 1 = -2e14、R = 2E14。 (L <R){一方 LLミッド=(L + R)>> 1。 IF(解く(MID))L =ミッド+ 1。 他のR =ミッド; } のprintf( "%LLDする\ n"、L)。 } }