リファレンスから:https://blog.csdn.net/XY20130630/article/details/50635756
質問の意味:配列が退屈しないことが知られており、その連続したサブシーケンスの各々に対して一意の番号が存在する場合にのみされる
少なくとも一桁の存在下で、各配列は一度だけ現れます。
それは退屈でない場合、整数のシーケンスを考えると、あなたが決めます。
分析:前処理は各要素と位置の次の出現に現れ、
我々はシーケンス[L、R]のためのものであることを見出し、
[I] <L && NXT [I]> R&LTこの配列で、特定の予め存在する場合条件を満たしている、
または満たしていない、我々は、パーティションの問題に対処
し、複雑さのそれぞれが、小さい方の2系列に分割されて開いて、この私を見つけるために、両側から真ん中に
これはあります合わせた逆ヒューリスティックプロセス、O(nlogn)の複雑
まず、間隔要素P(そうでない場合、配列は、退屈)の唯一つの存在を見つける[L、R]で
第二に、再帰的な処理区間[L、P-1]、区間[P + 1、R]
キーは一度だけ表示される要素を見つける方法です。
まず、要素が一回だけがないかどうかを判別する方法を知っている必要があります。
我々は、位置の記録素子STLにマップは、現在の要素の値(次の要素)と同じで使用することができ、その後、ロールオーバーします。
以来、すべてのマップ操作はO(LOGN)は、プレO(nlogn)の時間計算量となるよう
そこで、我々は一度しか判断表示されていませんO(1)時間要素を使用することができます。
右に左には、シーケンス全体をスキャンする場合、最悪の場合、配列中の最も右側の要素は、
T(N)= T(N -1)+ O(N)≥T(N2)= O(N 2)
二分法は、一般的に数にできるだけ近い2列に分かれて、我々は考えることができます可能である見つけるために、中央には2つの側面を。(これは、ヒューリスティックである)
このとき、シーケンスの途中でこの要素の最悪の場合には、その後、
T(N)= 2T(N / 2)+ O(N)、 T(N)を解く= O(nlogn )
だから、Oの合計時間の複雑さ(nlogn)
#include <iostreamの> する#include <cstdioを> する#include <アルゴリズム> の#include <地図> 使用して 名前空間STD。 const int型 MAXN = 2E5 + 5 。 int型のn; INT プレ[MAXN]、NXT [MAXN]、[MAXN]。 マップ < int型、int型 > 融点; ブールチェック(int型 L、INT R){ // 先预处理プリ、NXT 場合(L> = R)を返す 真。 int型、L = L、R = R。 以下のための(INT I = Lは、I <= R&LT;私は++が){ // 両側から中間分析する、意志形而上の複雑さを低減し、ポイントを見つけることを目的と IF(I&1。){ IF(予備[L] <L && NXT [ L]> R&LT){ // 満たす予め[i]は<L && NXTは、 [I]> Rは、この点では一致する 戻り、L-をチェック(Lを1 L +()&&チェックする。1、R&LT); //は残りを判断することができますサブ } L ++ ; } そうでなければ{ IF(PRE [R&LT <L && NXT [R&LT]> R&LT){ 戻りチェック(L、R- 1。 &&チェック(R&LT +)1 、R&LT)。 } R- ; } } を返す 偽。 } int型のmain(){ int型のT。 scanf関数(" %のD "、&T)。 一方、(T-- ){ scanf関数(" %のD "、&N) 以下のために(int型私= 1 ; iが<= N; iが++ ){ scanf関数(" %のD "、A + I)。 } mp.clear()。 用(int型 iは= 1、I ++; iが<= N。){ 事前[I] = 融点[I]]。 NXT [MP [I]]] = I。 MP [I] = I。 } のために(int型 i = 1 ; iがn = <; iは++ ){ NXT [MP [I]]] = N + 1 。 } であれば(チェック(1、n))をプット(" 非退屈" )。 他のプット(「退屈」); } }