質問の意味:一番高い木に残っている木の数が半数以上を占めたように、n個の木があり、コストや数量の除去、それぞれに高い数値を与え、多くの最小値を過ごす求めています。
分析:すべての高さは、この高い評価を受けて最大の高さの現在の列挙に、num個の木の数は、その後、彼のためよりも高いのカットバックしてください非常に規則正しい列挙し、ので、彼よりも小さい考えます二重の関係を構成するので、NUM-1ケまで保持します。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型 N = 205 ; const int型 M = 1E5 + 5 。 LLツリー[N] [ 2 ]。 構造体ノード{ LLのH、P、C。 } [M]。 LL sufc [M]、sufp [M]。 BOOL CMP(ノードP、ノードq){ 戻り pHが< QH。 } ボイド追加(int型 Uは、LLのx、int型I){ 一方(U <= 200 ){ ツリー[U] [I] + =バツ; U + = - U&U; } } LLのSUM(int型、Uをint型i)が{ LL ANS = 0LL。 一方、(U){ ANS + = [I]ツリー[U]。 U - = - U&U; } 戻りANS。 } int型のmain(){ int型N; 一方、(〜のscanf(" %d個"、&N)){ memsetの(木、0LL、はsizeof (木))。 LLの合計 = 0、MAXC = 0、ミンク=M; 以下のために(int型 i = 1 ; iが<= N; iは++ ){ scanf関数(" %LLD%LLD%LLD "、および[I]・H、・[I] .C、および[I] .P)。 和 + = A [i]の.P。 MAXC = MAX(MAXC、[I] .C)。 ミンク = 分(ミンク、[I] .C)。 } ソート(A + 1、+ 1 + N、CMP)。 以下のために(int型 I = N; I> = 1 ; i-- ){ sufc [I] = sufc [I + 1 ] + [I] .P * [I] .C。// 后缀代价总和 sufp [I] = sufp [I + 1 ] + [I] .P。// 后缀树木总数和 } LL ANS = sufc [ 1 ]。 int型 I = 1 ; / * (I = 1をint型、iが<= N; iが++)のため COUT << sufc [I] <<」「。 coutの<<てendl; * / ながら(iは= < n)を{ int型 L = I、R = I。 LL NUM = 0LL、needcost = 0LL。 一方、(R <= == .H N && [R] [L]・H) NUM + = [R ++ ] .P。 needcost + =sufc [R&LT]; LL必要 = SUM-NUM-SUFP [R&LT] - (num- 1。); // 現在の最大高さとして同定列挙には、確かに現在のカットオフよりも高く、そしてその後に起因して、両方の正面検討します回、そう最大カット・ツリーNUM-1 IF(必要<= 0 ) ANS = 分(ANS、needcost); 他{ LLのL =ミンク、R&LT MAXC =、S = 0LL; ながら(L <= R&LT){ MIDD LL =(L + R&LT)>> 1。; IF(SUM(MIDD、0)> = 必要) S = MIDD、= R&LT midd- 1。; 他 L = + MIDD 。1 ; } 必要 - SUM =(S、0 ); needcost + SUM =(S、1 ); // 貪欲を維持するように、そしてそう余分を失うまでの時間を削減するために、プレフィックスツリーよりも大きいがあります考慮 needcost- = S * ABS(必要); } ANS = 分(ANS、needcost); 一方、(L < R&LT){ 追加(A [L] .C、A [L] .P、0 ); 追加( [L] .C、A [L] .C * A [L] .P、1。); L ++ ; } I= R。// coutの<< R <<てendl; } のprintf(" %LLDする\ n " 、ANS)。 } 戻り 0 。 }