P1020ミサイル迎撃(最長シーケンス上昇/最大長シーケンスを落下- O(N 2 O)は(NlogN)アプローチ)
質問の意味:
ありnは異なる高さで飛んでミサイルの数、迎撃ミサイルは、いくつかのミサイルは非常に上昇している傍受することができ、迎撃ミサイルを尋ねる星の数にミサイルの最大数、ミサイルインターセプトすべての迎撃ミサイルを迎撃することができます
アイデア:
最初の質問:ミサイル迎撃ミサイルの最大数を傍受することができ、これは要求がサブシーケンスの問題が落ちることはありませんでした最長です
O(N検討2高さ未満又はに等しい場合、更新しようとすることができ、各ミサイルのために、我々の以前のミサイルの前方移動のそれぞれを)アプローチをDP [I] = MAX(DP [i]は、DP [J] +1)
各要素のDP [I]が1に初期化されます
見てみましょうトラバースは、O(nlogn)アプローチする前に、チームは我々が最適化するのに選択することができ、ここで各要素に近づく前進しました
下付き数字製ツリーアレイを、確立最大長を維持し、前方のサイクルから、木の数は、アレイの内部に配置されています。この数に各クエリは、系列長の最後まで上昇しない前最大、この最大長さ+ 1最長シーケンスがツリーにアレイの内側に、それ自身の端に上昇しないように
2番目の質問:どのように多くのミサイルの最小値を依頼します
使用するにはディルワース定理を
ディルワース定理:抗鎖Posetの最小数が最長の鎖の長さに等しく分割
私たちは、単に上昇最長のシーケンスを求めて、それは簡単なことを証明しようとしています
ミサイルは方法があるようですヒットと仮定すると、(1):任意のミサイルを取るには、ミサイルのミサイルは、すべての完成を再生するために開始します。これらのミサイルはすべて同じグループに言及した後、必要に応じてダウンミサイルで上記のステップを繰り返して、すべてのミサイルキックまでは再生できませんでした
(2)+ 1グループからミサイルよりミサイルの高さを見つけることが可能であるべきである、(1 <= <= K)基ミサイルのいずれかがミサイルを取るから、我々は最小の分割K基のミサイルを得たとし高(見つからなかった場合、それはより多くの任意の高導電率に+ 1のグループよりも、+を置くべきであるミサイルの最初のグループを演奏グループで一緒に横たわっていたのではなくグループ1 +として分類され、他のすべてのために)、真の+ 1、A + 2セットから同じグループ。そして、あなたも、長さKで上昇シーケンスとして、さらに高いアップミサイルにフロントからバックに、各グループ内で見つけることができます
<;増加し、二つのグループのいずれかで最長の配列が同じでない(又は満足単調リットルではない)ので、ある= P(3)は、最長シーケンスの長さがPであり、Kが提供される増加P> = Kが、K = Pそう
#include <iostreamの> する#include <アルゴリズム> の#include <CStringの> する#include <cstdioを> の#define lowbit(X)(X&( - x))を 使用して、 名前空間STD。 const int型 MAXN = 100100 ; INT、N = 0 、lenの; int型[MAXN]、MX [MAXN]と、 ボイド追加(int型のx、int型のval) { 一方(X <= MAXN){ MX [X] = MAX(MX [X]、ヴァル)。 X + = lowbit(X)。 } } int型のクエリ(INT X) { int型 ANS = 0 。 一方、(X> = 1 ){ ANS = MAX(MX [x]は、ANS)。 X - = lowbit(X)。 } 戻りANS。 } int型のmain() { 一方(scanf関数(" %のD "、&[++ N])= EOF!)。N - ; int型 ANS = 0 ; 用(INT I = N; I> = 1 ; i-- ){ int型のx =クエリ([I])+ 1 。 ([I]、x)を追加します。 ANS = MAX(ANS、X)。 } COUT << ANS << ENDL。 memset(MX、0、はsizeof (MX))。 ANS = 0 ; 以下のために(INT iが= 1 ; I <= N; I ++ ){ int型のx =クエリ([I] - 1)+ 1 。 ([I]、x)を追加します。 ANS = MAX(ANS、X)。 } COUT << ANS << ENDL。 リターン 0 ; }