質問の意味:
3つの配列、A、B、Cがあり、各動作が別の配列と配列において携帯電話の番号とすることができます、
Q、最小の操作を数回、それは以下の配列の内部におけるBのすべての数の全ての数、内部cよりも小さいBよりも引き起こし得ます。
デジタルデータの量に、2E5の合計が繰り返されていません。
アイデア:
実践:(LIS)
このアプローチでも100の後のシーケンスでは、この方法を使用して、実際にはかなり巧妙な、見に沿ったものである、必要性を恐れません。
それぞれABC、ソートされ、その後、合併
最大立ち上がりシーケンスを求めて、次に数列の上昇が移動しない、非シーケンシャルにのみ移動、答えがn - lenを、LEN最大、答えは最小です。
それはフェンウィックツリー最適化と、LISの時間を探しているので、O(Nを記録*に複雑であるn-は )。
練習2つのファック:()
これはO(n)のの複雑さのうちだと思うし、自分自身を盲目であるが、唯一の3つのシーケンスに適用されます。
シーケンス内の三つ、C1見三色の色、C2、C3、および並べ替えと混合と称される、
各タイム左固定点Lは、シーケンス番号の最後の1〜Lに示し、次に、ルックアップ操作は、右点Rを最小限に抑えることができ、その後、+ 1〜R系列bの数の最後のLを表します残りのR + 1〜Nシーケンスcの数です。
それはrの最小動作の右のポイントを見つける方法、lは、あること、存在しない場合、我々は今だけシーケンスが2つのセクションに分かれていると仮定
右端点Iは、明らかに、オペランドの数は〜C3、I + 1 IプラスN、C2の数に1である場合(このBC動作シーケンスの必要数)(ウェルの操作の回数は求めて、)レーンC1 1〜Lの数ではありません
移動するとき、嚥下C3場合、その後は、R L + 1〜Nの各時間点をオペランドが全てマイナス1であるため、最小変化の位置のでなぜL、Lの存在を想定することができないが、マイナスの値のみ。
2点のみ、我々は簡単にするとき、これは楽しみのようになります更新からn個〜jの最小値rを見つけることができます。
だから、要するに、その後、事前-jの最小〜N Rで、列挙L、更新解答位置です。
(私は思ったびに質問が...混乱のすべての思考を置きます)
コード:
実践:(LIS)
書式#include <stdio.hに> する#include < 文字列の.h> の#include <アルゴリズム> 書式#include <ベクトル> の#include <キュー> の#include <機能> 使用して 名前空間はstdを、 const int型 MAXN = 2E5 + 10 。 const int型 INF = 0x3f3f3f3f 。 int型DP [MAXN]、MX [MAXN]。 int型 lowbit(INT I){ 戻り Iを&( - I)。 } のボイド挿入(int型 I、int型のx、int型N){ ながら(I <= N){ MX [I] = MAX(MX [I]、X) I + = lowbit(I)。 } } int型 _find(INT I){ int型 RES = 0 。 一方、(I> 0 ){ RES = MAX(MX [i]は、RES)。 I - = lowbit(I)。 } 戻りRES。 } INT LIS(INT A []、INT N){ int型 RES = 0 。 memsetの(MX、0、はsizeof (MX))。 memsetの(DP、0、はsizeof (DP))。 以下のために(INT iが= 1 ; I <= N; I ++ ){ DP [[I] = _find([I])+ 1 。 RES = MAX(RES、DP [I])。 インサート([I]、DP [I]、N)。 } 戻りRES。 } int型[MAXN]、B [MAXN]と、 INT のmain(){ int型 _n [ 3 ]、N。 一方、(scanf関数(" %D%D%D "、&_ N [ 0 ]、&_ N [1 ]、&_ N [ 2 ])!= EOF){ N = 0 。 int型 CNT = 0 ; 用(int型のk = 0 ; K < 3 ; K ++ ){ ため(intは iは= 1、I ++; I <= _n [K] ) のscanf(" %dの"、&B [I])。 ソート(B + 1、B + _n [K] + 1 )。 以下のために(INT iが= 1 ; I <= _n [K]; I ++) [ ++ CNT] = B [i]は、 N + = _n [K]。 } INT ANS = LIS(N) printf(" %dの\ N "、N - ANS)。 } 戻り 0 。 }
練習2つのファック:()
する#include <stdio.hに> する#include < 文字列・H> の#include <iostreamの> する#include <cmath> の#include <ベクトル> の#include <キュー> の#include <アルゴリズム> 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型 MAXN = 2E5 + 10 。 INT SUM2 [MAXN]、SUM3 [MAXN]、mi_p [MAXN]、MI [MAXN]。 int型VIS [MAXN]。 INT のmain(){ int型N1、N2、N3、X、N。 しばらく(scanf関数(" %D%D%D "!&N1、およびN2、およびN3)= EOF){ memsetの(VIS、0、はsizeof (VIS))。 N = N1 + N2 + N3。 以下のために(INT iが= 1 ; I <= N1; I ++ ){ scanf関数(" %のD "、&x)は、 VIS [X] = 1 。 } ため(INT iは= 1 ; I <= N2; I ++ ){ scanf関数(" %のD "、&x)は、 VIS [X] = 2 ; } ため(INT iは= 1 ; I <= N3; I ++ ){ scanf関数(" %のD "、&x)は、 VIS [X] = 3 ; } SUM3 [ 0 ] = 0 ; 以下のために(INT iが= 1 ; I <= N; I ++ ){ SUM3 [I] = SUM3 [I - 1 ]。 もし(VIS [I] == 3 ) SUM3 [I] ++ ; } SUM2 [N +1 ] = 0 ; 用(INT I = N; I> = 1 ; i-- ){ SUM2 [I] = SUM2 [I + 1 ]。 もし(VIS [I] == 2 ) SUM2 [I] ++ ; } INT mival = SUM3 [n]は、ANS = 1E9。 MI [N] = SUM3 [N]。 用(INT I = N - 1 ; I> = 1 ; i-- ){ MI [I] = MI [I + 1 ]。 もし(mival> SUM3 [I] + SUM2 [I + 1 ]){ mival = SUM3 [I] + SUM2 [I + 1 ]。 MI [I] = mival。 } } MI [ 0 ] =分(SUM2 [ 1 ]、MI [ 1 ])。 INT = 1 0、サブ= 0 、RES。 ANS = N2 + N3。 以下のために(INT iが= 0、I <N; I ++ ){ 場合(VIS [I] == 1 ) 1 ++; もし(VIS [I] == 3 ) サブ ++ 。 RES =(I - 1)+ MI [I] -サブ+(N1 - 1)。 もし(RES < ANS) ANS = RES。 } のprintf(" %dの\ n " 、ANS)。 } 戻り 0 。 }