もちろん、言葉が繰り返されていない場合の数字は、直接貪欲塗りつぶしが正しい表示されます。
しかし、この貪欲重複番号が間違っています。
ツリーに抽象問題が明らかです。
私たちの最大から最小へのすべての行番号の最初の。
$サイズの大きさ[i]は$ $ I $のために、これは最初の$のサイズを選出するための現在の選挙は確かにある[i]と$大。(TO $ X $)
X $ $サイズ[i]は$場所は私が$$する前に、次に、選択された$ X $の完了後、$は明らかに予約する必要があります。
各点は$ F [i]が$の最大数を表していると仮定して、我々は明らかに$サイズ[i]が<= F [J] $と私は$ $の最大値を満たすように選択し、$ I $前の数を記入することができます。
プロセスは、$ J $バイナリツリーのオンラインセグメントを見つけ、その後、フラグの付いた場所ができ見つけるために。
コード:
#include <ビット/ STDC ++ H> に#define LL長い長 の#define LSON今<< 1 今の#define rson << 1 | 1 の#define N 500006 の#define setIO(S)(S freopenは".IN"、「R 」、)標準入力 名前空間stdを使用。 INTミネソタ州[N << 2]、タグ[N << 2]、サイズ[N]。 ボイドビルド(int型のL、R INT、INT今) { IF(L == R){ミネソタ[今] = L。リターン; } int型のミッド=(L + R)>> 1。 ビルド(L、中間、LSON)、ビルド(MID + 1、R、rson)。 ミネソタ州[今] =分(ミネソタ州[LSON]、ミネソタ州[rson])。 } ボイドマーク(int型のx、int型V) { タグ[X] + = V。 ミネソタ州[X] + = V。 } ボイドプッシュダウン(INT今) { IF(タグ[今]) { マーク(LSON、 マーク(rson、タグ[今])。 タグ[今] = 0; } } (現在のint L、R INT、INT、INT L、INT R、int型V)ボイド更新を { IF(L> = L && R <= R) { マーク(ここで、V)。 リターン; } プッシュダウン(今)。 INTミッド=(L + R)>> 1。 IF(L <= MID) 更新(L、中間、LSON、L、R、V)。 IF(R> MID) 更新(MID + 1、R、rson、L、R、V)。 ミネソタ州[今] =分(ミネソタ州[LSON]、ミネソタ州[rson])。 } INTクエリ(INT L、INT R、今INT、INT K) { IF(L == R)リターンミネソタ[今] <K(L + 1):L。 INTミッド=(L + R)>> 1。 プッシュダウン(今)。 IF(ミネソタ州[rson]> = K) (L、中間、LSON、k)は、クエリを返します。 他の リターンクエリ(ミッド+ 1、R、rson、K); } INT W [N]、ヴァル[N]、NXT [N]、FA [N]、CLR [N]、[N] ANS。 ブールCMP(int型B、INT){> Bを返します。} int型のmain() { // setIO( "入力")。 int型I、J、N。 ダブルTMP; scanf関数( "%D%LF"、&N、&TMP)。 ための式(I = 1; iが<= N; ++ I) のscanf( "%dの"、および[I] W)。 ソート(+ 1 + nは、CMP W 1 + W)。 - (I; I> = 1 iがN =)用 { ++サイズ[I]。 NXT [I] = I。 FA [I] =(INT)(1.0 * I / TMP)。 サイズ[FA [I] + =サイズ[I]。 IF(I = N && [I] == W W [I + 1]!) NXT [I] = NXT [I + 1]。 } ビルド(1、nは、1)。 ため(I 1 =、iが<= N; ++ i)が { IF(FA [I] &&! アップデート(1、nは、1、ANS [FA [I]、nは、サイズ[FA [I]] - 1)。 CLR [FA [I] = 1。 } ANS [I] =クエリ(1、nは、1、サイズ[I])。 ANS [I] = NXT [ANS [I]]。 アップデート(1、nは、1、ANS [i]は、N、-size [I])。 } のためには、(i 1 =; I <= N; ++ I) ([ANS [I] W "%のD")のprintf。 0を返します。 }