簡単なタイトル:
所与\(1 \) 〜\(N- \)を見つけるために、配置された(\ B)を\の中央値である連続したサブシーケンス及び奇数の長さ数。
明らかに、このシーケンスには\(b \)が含まれています。
中央値の定義:ソート後の中央の数値。
アルゴリズム1
用(30 \%\)\、データ\(N- \のLeq 100 \) 。
このシーケンスには\(b \)が含まれている必要があるため、間隔\([i、j] \)に\(b \)が含まれている(ダブルポインターと同様)と列挙して、\([i、j ] \)この段落は暴力的な判断で並べ替えることができます。
時間の複雑さ:\(O(n ^ 3 \ log n)\)。
実際のスコア:\(30pts \)。
アルゴリズム2
(60 \%\)\、データ\(N- \のLeq 1000年\) 。
もちろん、毎回\([i、j] \)を取り出す必要はなく、何度でも展開できます。
\(i \)を列挙すると(\(d \)から\(1 \)まで)、\(d \)は\(b \)の場所です)、\(dから\(j \)を列挙します\) To \(n \)。\(j \)ごとに、元の配列に\(a_j \)を追加するだけです。\(j = n \)の場合は、配列は空です。
そして、単語の数を挿入するために、各唯一の必要性、我々は使用することができます挿入ソートを、それがソートされているように、挿入位置が半分で計算することができますので、注文しています。挿入操作に配列のメンテナンスは必要ありません。\(\ text {vector} \)を使用したメンテナンスの方がはるかに便利です。
時間の複雑さ:\(O(n ^ 2 \ log n)\)。
実際のスコア:\(60pts \)。
アルゴリズム3
(60 \%\)\、データ\(N- \のLeq 1000年\) 。
並べ替えのプロセスは別として、整理の性質上、繰り返しはありません。したがって、連続した配列の中央値\(B \)と比場合だけ\(B \)多数と数比\(B \)の値の小さい方の数が等しいです。だから、のために\(D \)線形の左側に\(\テキスト{DP} \)と\(F_iと\)を表し\(I \) 〜\(D \)より\(I \)多数の\(g_i \)の数は少なく、\(d \)の右もまた押されます。
次に、左と右のエンドポイントを列挙します\(i、j \)は、\(O(1)\)だけで判断できます。つまり、\(f_i + g_i = f_j + g_j \)です。
時間の複雑さ:\(O(n ^ 2)\)。
実際のスコア:\(60pts \)。
アルゴリズム4
(60 \%\)\、データ\(N- \のLeq 1000年\) 。
アルゴリズム3の\(\ text {dp} \)から始めて、\(f_i + g_i = f_j + g_j \)は\(f_i-f_j = g_i-g_j \)と同等であることがわかります。したがって、計算する必要があるのは比\(B \)値の数よりも大きい\(B \)の数の数の小さい差として再利用(\ F)\状態配列の、その後のエンドポイントを挙げることができます。
時間の複雑さ:\(O(n ^ 2)\)。
実際のスコア:\(60pts \)。
アルゴリズム5
用(100 \%\)\データ、\(N- \ 1当量5 ^ 10 \) 。
4番目のアルゴリズムから最適化しましょう。実際、左端が固定されている\(i \)の場合、\(j \ geq d \)と\(f_i = f_j \)の数を計算するだけで済みます。
言い換えれば、我々は維持する必要があるの問い合わせの数に等しい間隔を。
IQだけでは不十分で、データ構造がまとまります。したがって、このクエリには\(\ text {Treap} \)または\(\ text {Splay} \)を使用できます。(どのバランスボードでも使用可能)
時間の複雑さ:\(O(n \ log n)\)。
実際のスコア:\(100pts \)。
アルゴリズム6
用(100 \%\)\データ、\(N- \ 1当量5 ^ 10 \) 。
アルゴリズムフィフスから始めて、あなたはそれを見つけるの間隔は、お問い合わせの数と同じであることは変更せずに、静的なクエリです。次に、あなたが使用することができ重みがツリーライン(ツリーの会長を)この問題を解決します。
時間の複雑さ:\(O(n \ log n)\)。
実際のスコア:\(100pts \)。
アルゴリズム7
用(100 \%\)\データ、\(N- \ 1当量5 ^ 10 \) 。
6のアルゴリズムに基づいて、あなただけではなく、静的でなく、一定の間隔を見つける\([D、N-] \) 。だから我々は必要ありません重みセグメントツリーを(として理解することができます\(N \)の木のツリーライン)、\(1 \)の線分ツリーのみが必要です。
時間の複雑さ:\(O(n \ log n)\)。
実際のスコア:\(100pts \)。
アルゴリズム8
用(100 \%\)\データ、\(N- \ 1当量5 ^ 10 \) 。
プログラムが7番目のアルゴリズムで停止した場合、それはあなたが天才であることを示すだけで、最終的な成功からほんの数歩しか離れていません。
固定間隔は、静的に等しい数を維持します。これは非常に高いようですが、実際には\(\ text {map} \)ですか?
クラスメート:まだできます%$#^%*(%&))
さて、\(\ text {map} \)に変更すると、ずっとシンプルに感じられますよね?次に、\(f \)配列を直接省略して、\ (\ text {map} \)に直接保存します。
時間の複雑さ:\(O(n \ log n)\)。
実際のスコア:\(100pts \)。
//为了看起来清晰 , 用了嵌套三目运算符
// q[tot+=((a[i]>b)?1:(a[i]<b)?-1:0)]++; 其实相当于这几句:
// if(a[i]>b) tot++;
// if(a[i]<b) tot--;
// q[tot]++;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+1;
inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
int n,b,wz,a[N];
int tot,sum; ll ans=0;
map<int,int> q;
int main(){
n=read(),b=read();
for(int i=1;i<=n;i++) a[i]=read(),wz=(a[i]==b)?i:wz;
for(int i=wz;i<=n;i++) q[tot+=((a[i]>b)?1:(a[i]<b)?-1:0)]++;
for(int i=wz;i>=1;i--) ans+=q[0-(sum+=(a[i]>b)?1:((a[i]<b)?-1:0))];
printf("%lld\n",ans);
return 0;
}
アルゴリズム9
用(200 \%\)\データ、\(N- \ 1当量7〜10 ^ \) 。
(実は自分の援軍)
アルゴリズム8に基づいて、この\(\ log \)を削除することができます。
しかし、すぐに、下付き文字は\(10 ^ 7 \)を超えないが、負の数、おそらく\(- 10 ^ 7 \)になることがわかりました。
明らかに、負の添え字をハッシュすることは、この問題の最終的な正の解決策です。
各添え字に\(n \)を追加します。負の添え字\(O(1)\)クエリを解決した後、\(\ text {map} \)を削除して\(\ log \)を解決します。
時間の複雑さ:\(O(n)\)。
実際のスコア:\(200pts \)。