私たちは、午後に木を植え、そして最終的には(あなたがはっきりポイント(目に見えない目に見えない)を話すことができない問題に(問題解決の偉大な神をありがとう)(溶液))それを与えました。
あなたは木を持っているK、あなたができる種類の直線で、あなたは、この値を得ることができます木を置けば、それぞれの場所には、値を持っていますが、条件は、任意の2本の隣接する木がありません。
もちろん、あなたは0をkに任意の木を植えることができます。
どのようにそれを行うには?この質問は、(まれ)問題の良心であり、私が選択したか、選択されていない。この位置を列挙し、脳の暴力なしで最初の20分を書きました。
書式#include <cstdioを> する#include <CStringの> の#include <アルゴリズム> 使用して 名前空間はstdを、 const int型 MAXN = 5E5 + 10 。 typedefの長い 長いLL。 int型N、K。 INT [MAXN]。 INT [MAXN] B。 ANS LL; LLのCNT; ボイド DFS(INT X) { 場合(X == N + 1 ) { LL和 = 0 。 int型 NUM = 0 ; 以下のための(int型i = 1 ; iは= <N; iは++ ) { 場合(B [I] == 1件の && B [I- 1 ] == 1)リターン; もし(B [I] == 1 ) { NUM ++ 。 場合(NUM> k)を返します。 和 + = (LL)[I]。 } } ANS = MAX(ANS、合計)。 返します。 } [X] B = 0 ; DFS(X + 1件の)。 B [X] = 1 ; DFS(X + 1 )。 } int型のmain() { scanf関数(" %D%dの"、&N&K)。 以下のために(int型私= 1 ; iが<= N; iが++)のscanf(" %dの"、および[I])。 DFS(1 )。 printf(" %のLLD " 、ANS)。 リターン 0 ; }
しかし、あなたは20ポイントに喜んで、これは直線であると考えることができますどのように、あなたはDPは、わずか50ポイントでパスを貼り付け使用することができます。
[I] [j]は、現在位置1からI jの木植え最大値の合計を表すfはそれがあります。
電流は木、[I-1] [j]はF直接コピーされていない場合、彼らは木を望むなら(それは隣接していないため)、[I-2] [J-1] fをコピーします
書式#include <cstdioを> する#include <CStringの> の#include <アルゴリズム> 使用して 名前空間はstdを、 const int型 MAXN = 5E5 + 10 。 typedefの長い 長いLL。 int型N、K。 LL [MAXN]。 ANS LL; [F LL 6010 ] [ 3010 ]。 INT メイン() { scanf関数(" %d個の%のD "、&N&K)。 用(int型 I = 1のscanf(私は++; iが<= N)" %のLLD "、& [I])。 [F 1 ] [ 1 ] = [ 1 ]。 以下のために(int型 I = 2 ; iは++; iが<= N ) { ため(int型の J = 1 ; J <= kであり、j ++ ) { F [I] [J] = MAX([I-F 1 ] [j]は、 F [I- 2 ] [J- 1 ] + [I])。 ANS = MAX(ANS、F [i]は[J])。 } } のprintf(" %のLLD " 、ANS)。 リターン 0 ; }
時空の制約が、私は、ああ良いガスから抜け出すことはできません。
最後に、私は(目が光を発する)問題への解決策を開設しました
三ヶ月後……
私たちは、誰のどのような種類を制御していない人、後者は、限り最大値として、
私たちは、これがそれから来ているか、プライオリティキューを使用できますか?連続面3(第一の又は自由端位置)の数は、符号1,2,3を参照します。
私たちは第二の穴を選択した場合は、その後、1,3スクラップこと。
(!!あなたが達成するためにプライオリティキューを)(私はこの種のものを分析したくない表す);あなたは1.3を選択した場合は、2を選出することはできません
私たちは、ヒープのトップは、我々が探している最大でデフォルト、しかし、我々はいくつかの処理を通過する必要があります。
R [I] = I + 1;左右の各点の位置を端部はL [I] = I-1に記録されています
最初のピットに投げ込まN、その後、ヒープの上部には、我々はANS + = valを取り出して、その最大値になります(なぜ、1,3-行う方法を?)
我々はオプション1、3、1、3を選択することはできませんので、それは問題ではありません、我々は選択しないと、2の値が取り出され、その後、2の値を更新し、
ヴァル[2] = valの[1] +ヴァル[3] -Val [2];(ANS値を更新する必要があります)
しかし、我々は繰り返しを避けるために選択し、VIS [1] = VIS [3] = 1;(特別ではないアクセス)
3の3つのグループに分けグループをしているのと同等であり、我々はあなたが2アップデート(0,2,4になるための同等のもの)を配置したい値についての最新情報を掲載します
実際には、我々は最後まで3つの接続されたエンドのグループで問題が解決されます(私たちは1,3を選択したい場合は、私たちはこの時間を更新するパターン、再び2 0,2,4である、彼らは接続されません。)
(1,3及び0,4から選択すると比較されました)
処理が完了しています。
杭は、行に終了し、負である場合には、
書式#include <cstdioを> する#include <CStringの> の#include <キュー> の#include <アルゴリズム> 使用して 名前空間はstdを、 const int型 MAXN = 5E5 + 10 。 typedefの長い 長いLL。 INT [MAXN]。 int型N、K。 INTをL [MAXN]、R [MAXN]。 PRIORITY_QUEUE <ペア< int型、int型 >> Q; ANS LL; int型VIS [MAXN]。 INT メイン() { scanf関数(" %d個の%のD "、&N&K)。 以下のために(int型 i = 1 ; iが<= N; iが++ ) { scanf関数(" %dを"&[I])。 // [I] .val = -a [I] .val。 q.push(make_pair([i]は、I))。 L [I] = I- 1 。 R [I] = I + 1 。 } R [ 0 ] = 1 ; Lが[N + 1 ] = N。 一方、(k-- ) { 一方(VIS [q.top()秒])q.pop(); INT X = q.top()最初。 int型I = q.top()は、第2。 q.pop(); もし(X < 0)ブレーク。 ANSは + = (LL)X; [I] [L [i]は] + [R [I] = - [I]を、 VIS [L [I] = 1 ; VIS [R [I] = 1 。 L [I] = 1 [L [I]、R [L [I] = I。 R [I] = R [R [I]、L [R [I] = I。 q.push(make_pair([i]は、I))。 } のprintf(" %のLLD " 、ANS)。 リターン 0 ; }
これらの慣行とコードサイズを見て、あなたは(それを行うのは難しいです)(〜をエスケープ)この問題は思います。