トピック:
いくつかの最近の研究は逆のようなNK、列数は... A3、A2、nは... 1からなるA1、
逆順A1 A2の数は...され、数がA1、A2の数と逆の数であるA3 ...に.An A2少数よりも、などの数よりも小さいです。
例えば、列の数は、逆数列5,3,4,2,1 4,2,2,1,0です。
だから、列数の逆の順序で与えられた数列ならば、あなたは彼のオリジナルシリーズを復元することができませんか?
★データ入力
各テストデータは、正の整数nです。カラム長は、数(1 <= N <= 500)を示し、値の元の範囲内の列の数は[1、N]です。
次いで、入力nは正の整数は(0 <= AI <N)愛
★データ出力
スペースで区切られた2つの数値の間の中間オリジナルシリーズ出力、。
入力例 | 出力例 |
5 4 2 2 1 0 |
5 3 4 2 1 |
最初の番号が記入見つけるのは難しいことではありません、問題の分析では、独自の以外のすべての数字は、その背後にあるので、最初の桁が4です。我々は、セットから、i番目のAIが彼のより少ない数を有する場合、第一の組におけるAI + 1はi番目の桁の大きい数であり、全ての数の組として、この数1〜Nであることができます削除されました。$ Oのnの値が(500ほど小さくないクロスセグメントツリーかかわらなく)が小さすぎるため、リストを完了するために使用されてもよい、セット保守複雑に使用することが可能である(N ^ {2})$、もちろん、セットアップし、より便利に書か維持、セットを維持することをお勧めします。ここで重みツリーラインを使用して、$ O(nlogn)$のアプローチを共有することができます。
最初のコードセットを貼り付け
#include <ビット/ STDC ++ H> 使用して名前空間STDを、 typedefの長い長いLL。 typedefの長いダブルLD; typedefの符号なしの長い長いULL。 typedefのペア < int型、int型 > PII。 #define担当者(I、x、y)がため(I = xをint型、I yを<; I ++) の#define REPT(I、x、y)がため(I = xをint型、iは= yと<; iは++) の#define当たり(I、x、y)は(I = int型のX; I> = Y; i--)のため の#define PB一back の#define Fiの第一 の#define SE第二 の#define MES(B)のmemset(A、B、はsizeof A) const int型 INF = 0x3f3f3f3f 。 設定 < 整数 > 秒; セット < 整数 > ::イテレータPOS。 int型のmain() { IOS :: sync_with_stdio(偽); cin.tie(0 )。 int型のn; cinを >> N; REPT(I、1 、N) s.insert(I)。 REPT(I、1 、N) { 場合(I- 1)COUT << " " 。 int型のx; CIN>> X; POS = s.begin()。 以下のために(int型 i = 0 ; iはXを<; iは、POSを++ ++ )。 coutの << * POS。 s.erase(POS)。 } COUT << " の\ n " 。 リターン 0 ; }
すべての1-Nの数、完了セグメントツリー、アレイのいくつかにポイントをマークし、i番目の各セグメントツリーのメンテナンス間隔の最大値を、各入力AI、第1のセグメントが、AIの数よりも大きい見つけるために間隔を残している点は、AIより大きく、左右のクエリ間隔がない区間の範囲を見つけるために残しました。双方向のi番目のアレイを想定し、各素子1の$ [1 + BI、N] $間隔を低減することができ、セグメントツリーは値0を割り当てであり両。
ACコードセグメントツリーを貼り付け
#include <ビット/ STDC ++ H> 使用して名前空間STDを、 typedefの長い長いLL。 typedefの長いダブルLD; typedefの符号なしの長い長いULL。 typedefのペア < int型、int型 > PII。 #define担当者(I、x、y)がため(I = xをint型、I yを<; I ++) の#define REPT(I、x、y)がため(I = xをint型、iは= yと<; iは++) の#define PB一back の#define Fiの第一 の#define SE第二 の#define MES(B)のmemset(A、B、はsizeof A)CONST INT MAXN = 505 。 LLのarrcy [ 100005 ]。 クラスツリー// 线段树 { パブリック: int型のL、R。 LLプラス、ヴァル。 ツリー() { L = R =ヴァル=プラス= 0 。 } }ツリー[MAXN << 2 ]。 ボイドビルド(int型 ID、int型の L、INT R)。 ボイド追加(int型 ID、int型の L、int型のR、LLのNUM)。 無効 push_down(int型のID); int型(見つけるint型の ID、int型NUM); INT のmain() { int型のn、X、ANS。 cinを >> N; ビルド(1、1 、N) 担当者(I、0 、N) { CIN >> X。 ANS =見つける(1 、x)は、 追加(1、ANS + 1、N - 1 )。 (追加1を、ANS、ANS、 - N)。 coutの << ANS << " " ; } 戻り 0; } ボイドビルド(int型 ID、int型の L、INT R) { ツリー[ID] .L = L。 ツリー[ID] .R = R。 もし(L == R) { ツリー[ID] .val =のL。 返します。 } INT半ば=(L + R)/ 2 。 構築(ID * 2 、L、ミッド)。 ビルド(ID * 2 + 1、中間+ 1 、R)。 ツリー[ID] .val = MAX(ツリー[ID * 2 ] .val、ツリー[ID *2 + 1 ] .val)。 } ボイド追加(int型 ID、int型の L、int型のR、LL NUM) { 場合(ツリー[ID] .L> = L &&ツリー[ID] .R <= R) { ツリー[ID] .plus + = NUM。 ツリー[ID] .val + = NUM。 返します。 } もし(ツリー[ID] .L> R ||ツリー[ID] .R <L)のリターン; push_down(ID)。 もし(ツリー[ID * 2 ] .R> = 1)(ID *追加2 、L、R、NUM)を、 もし(ツリー[ID * 2 + 1] .L <= R)を追加(ID * 2 + 1 、L、R、NUM)。 ツリー[ID] .val = MAX(ツリー[ID * 2 ] .val、ツリー[ID * 2 + 1 ] .val)。 } ボイド push_down(int型のID) { REPT(J、ID * 2、ID * 2 + 1 ) { ツリー[J] .val + = ツリー[ID] .plus。 ツリー[J] .plus + = ツリー[ID] .plus。 } ツリー[ID] .plus = 0 。 } int型の検索(int型 ID、INTNUM) { 場合(ツリー[ID] .L ==ツリー[ID] .R)リターン・ツリー[ID] .L。 push_down(ID)。 もし(ツリー[ID * 2 ] .val> NUM)戻り検索(ID * 2 、NUM)。 他の リターンのfind(ID * 2 + 1 、NUM); }