質問の意味:あなたは、n個のマトリョーシカ、知られているボリュームと彼女の各セットのボリュームを持っていますし、次の条件の多くのサブセットが満たされているか尋ねました。
1:これは、このサブセットの彼女の他のセットに追加することができない、偉大なサブセットのサブセットです。
2:人形と最小サブセットとの間のギャップ。
1を考える:最適化セグメントツリーDP:
大型の小最優先の最初の容積、第二プライオリティボリュームに記載の人形。提供ANS [i]は、最外層に人形i番目のサブインターバルのセットの最小の最大数、ANS [i]が1次回最小クリアランスを.second、我々は転送を行う:i番目の人形を仮定しますrは人形RのボリュームのボリュームをL1よりも大きく、ボリュームは、すべてのボリューム見つけることは簡単であり、R1、ボリュームは[L1、R1を - 1]人形の範囲は、現在の状態から移行してもよいです。ボリューム、最小クリアランス番号:我々は、特別な木のラインが転送をマークすることにより行うことができる、私はオンラインのセグメントツリーは3つのマーカーを維持しますよ。現在のボリュームであれば以下に - 怠惰な更新フラグは、分散型最小クリアランスを判定する。セグメントツリークエリのような単一のポイントは、対応するDP状態を得ることができます。
コード:
#include <ビット/ STDC ++ H> に#define LL長い長 の#define PLL対<LL、LL> の#define PII対<整数、整数> の#define LS(O << 1) の#define RS(O << 1 | 1) 名前空間stdを使用。 const int型MAXN = 200010; constのLL 1000000007 = MOD; 【MAXN] PII。 int型のval [MAXN]。 ワンセグ{構造体 LZ PLL。 int型のPOS。 }。 SEG TR [MAXN * 4]。 PLLは[MAXN] ANS。 BOOL V [MAXN]。 ボイドは、(PLL TMP、int型のP、O INT)を維持{ 場合{(tmp.first - TR [O] .POS - P <TR [O] .lz.first) TR [O] .lz = TMP、TR [O ] .POS = P。 }もしそうでなければ(tmp.first - P == TR [O] .lz.first - TR [O] .POS){ TR [O] .lz.second =(TR [O] .lz.second + tmp.second)%MOD。 } } ボイドプッシュダウン(INT 0){ (!= 0 TR [O] .lz.second)なら、{ (LS、TR [O] .lz、TR [O] .POS)を維持します。 (RS、TR [O] .lz、TR [O] .POS)を維持します。 TR [O] .lz = make_pair(1E18、0LL)。 TR [O] .POS = 0。 } } ボイドビルド(int型、L、O INT、INT R){ IF(L == R){ IF(ヴァル[L]){ TR [O] .lz = make_pair(0、ヴァル[L])。 TR [O] .POS = 0。 }他{ TR [O] .lz = make_pair(1E18、0); TR [O] .POS = 0。 } を返します。 } TR [O] .lz = make_pair(1E18、0); TR [O] .POS = 0。 INT半ば=(L + R)>> 1。 (LS、L、ミッド)を構築。 (RS、ミッド+ 1、r)を構築します。 } PLLクエリ(int型L、O INT、INT R、INT P){ {(L == R)場合 ANS [L] = make_pair(TR [O] .lz.first + [L] 1次回- TR [O] .POS、TR [O] .lz.second)。 戻りANS [L]。 } プッシュダウン(O) INT半ば=(L + R)>> 1。 IF(p <= MID)リターンクエリ(LS、L、中、P)。 他のリターンクエリ(RS、ミッド+ 1、R、P); } ボイド更新(INT 0、int型のL、INT R、INT QL、INT QR、INT P、PLL TMP){ IF(L> = QL && R <= QR){ (O、TMP、p)を維持します。 返します。 } プッシュダウン(O) INT半ば=(L + R)>> 1。 IF(QL <= MID)更新(LS、L、中間、QL、QR、P、TMP)。 IF(QR> MID)更新(RS、ミッド+ 1、R、QL、QR、P、TMP)。 } メインINT(){ int型のn; LLマイル= 1E18; scanf関数( "%d個"、 以下のために{(INT i = 1; iが++; iが<= N) scanf関数( "%D%dの"、および[I] .second、&[i]の1次回)。 } ソート(A + 1、A + 1個の+ N)。 <;(私は{= N I ++はiは1 = INT)のための (= MIブレーク;場合[i]が1次回)>を ヴァル[I] = 1。 MI =分(MI、(LL)[I] .second)。 } (1、1、n)を構築します。 MI = 1E18; (I 1 = int型、iが<= N; iが++){ため PLL TMP =クエリ(1、1、N、I)。 ANS [I] TMPを=。 INT POS1 = LOWER_BOUND(A + 1、A + 1 + N、make_pair([I] .second、[I] .second)) - 。 INT POS2 = LOWER_BOUND(A + 1、A + + N 1、make_pair([POS1] .second、[POS1] .second)) - - 1。 IF(POS1 <= n)を 更新(1、1、nは、POS1、POS2、[I] .second、TMP)。 (POS1 <= N)の場合{ Vの[I] = 1。 } } 以下のために(INT i = 1; iが= <N; iは++){ IF(V [i])と続けます。 MI =分(MI、ANS [i]が1次回)。 } LL RES = 0。 以下のために(INT i = 1; iが= <N; iは++){ IF(V [i])と続けます。 IF(ANS [i]が1次回== MI)のRES =(RES + ANS [I] .second)%MOD。 } のprintf( "%LLDする\ n"、RES)。 }
2つの:(彼らは直前の練習だろうが)PinkRabbitからのアイデアが、対象の性質は完全に発掘されていません。私たちは、およそ考えにシフト:状態は、我々は状態が現在の状態に転送することができるものを見たい、簡単にプレフィックスの現在の状態に転送することができ、ソート後に発見され、その後、我々は2つのポインタこのアプローチは、転送時に使用することができます。だから、新しい質問は、どのようにあなたは本当に現在の状態に転送することができますこれらのプレフィックス状態のどの知っていますか?セットF [i]はi番目の人形最小クリアランスであり、ANS [i]が最小クリアランスの数であり、A [i]は彼女のボリュームのi番目のセットであり、B [i]は、体積で、それらのプレフィックスほとんどの状態(状態Tであると仮定する)、F [T] - [T]は、現在の状態のように最小限の状態を転送することができます。最小の[t]を、その後転送を行う - このため、ちょうど2つのポインタのプロセスにおいてF [t]を維持しました。
コード:
#include <ビット/ STDC ++ Hが> の#define LL長い長い 名前空間stdを使用。 const int型MAXN = 200010; constのLL 1000000007 = MOD; P1、[MAXN]、B [MAXN]をINT [MAXN]、P2 [MAXN]。 【MAXN] ANS LL。 【MAXN] F INT。 BOOL器CMP1(int型のx、int型のY){ [X] <[Y]を返します。 } ブールCMP2(int型のx、int型のY){ 戻りB [X] <B [Y]。 } int型のmain(){ int型N、ED = -1。 scanf関数( "%のD"、&N); 以下のために(INT i = 1; iが<= N; iが++){ scanf関数( "%d個の%dを" &[i]は、&B [I])。 P1 [I] = P2 [I] = I。 ED = MAX(編、B [I])。 } ソート(P1 + 1、P 1 + 1 + N、CMP1)。 ソート(P2 + 1、P 2 + 1 + N、CMP2)。 int型POS = 1; int型MI = 0、合計= 1; 以下のために(; iがn = <; iは1 = int型私は++){ int型今= P2 [I]。 一方(POS <= N && [P1 [POS] <= bの[今]){ int型T = P1 [POS]。 IF(F [T] - [T] <MI){ MI = F [T] - [T]を。 和=のANS [T]。 }そうであれば(F [T] - [T] == MI){ 合計=(和+ ANS [T])%MOD。 } POS ++。 } [今] + MI [今] = B、F。 ANS [今] =合計。 } LL RES = 0。 MI = 1E9; 以下のために(INT i = 1; iが<= N; iは++){ ([I] <= ED)が続けば、 IF(F [i]が<MI){ MI = F [i]は、 RESの=のANS [I]。 }そうであれば(F [I] == MI){ RESの=(RES + ANS [I])%MOD。 } } のprintf( "%LLDを\ n"、RES)。 }