はここ
for (int i = 0; i < N; ++i) {
// 1. Add a[i] to all internal data structures
// 2. Calculate answers for all queries q such that r[q] == i
}
のようなものを私たちは、このループのO(N)
反復を持っており、私たちはデータ構造の両方の更新をしたい、のは、左から右への方法で、私たちのクエリと私たちの両方の要素を処理しようとo(N)
時間に現在処理されている部分の接尾辞を問い合せます。
は位置i
から始まるサフィックスがそうでなければ数j
と0
が含まれている場合のは1
を持つ配列contains[i][j]
を使用してみましょう。また、それぞれcontains[i]
の接頭辞の合計を計算したと考えてください。この場合、バイナリ検索を使用してO(log N)
時間内の各特定のサフィックスクエリに答えることができます:対応するcontains[l[i]]
配列の最初のゼロを見つける必要があります。これは部分和がインデックス+1でなくインデックス+1残念なことに、そのような配列はO(N^2)
のスペースを必要とし、更新ごとにO(N^2)
時間が必要です。
したがって、最適化する必要があります。 2次元のrange treeを "sum query"と "assignment"の範囲演算で構築しましょう。このようなツリーでは、任意の下位矩形の合計を照会し、O(log^2 N)
時間内のすべての下位矩形のすべての要素に同じ値を割り当てることができます。O(log^2 N)
時間で更新を実行し、O(log^3 N)
時間でクエリを実行できます。 O(Nlog^2 N + Qlog^3 N)
。空間複雑度O((N + Q)log^2 N)
(およびアレイの初期化のための同じ時間)は、遅延初期化を使用して達成されます。
UP: "sum"を含む範囲ツリーでのクエリの動作を修正しましょう。(この答えは長すぎることはありませまで)1次元の木のために、このようなものです:
class Tree
{
int l, r; // begin and end of the interval represented by this vertex
int sum; // already calculated sum
int overriden; // value of override or special constant
Tree *left, *right; // pointers to children
}
// returns sum of the part of this subtree that lies between from and to
int Tree::get(int from, int to)
{
if (from > r || to < l) // no intersection
{
return 0;
}
if (l <= from && to <= r) // whole subtree lies within the interval
{
return sum;
}
if (overriden != NO_OVERRIDE) // should push override to children
{
left->overriden = right->overriden = overriden;
left->sum = right->sum = (r - l)/2 * overriden;
overriden = NO_OVERRIDE;
}
return left->get(from, to) + right->get(from, to); // split to 2 queries
}
私たちの特定のケースでは、ツリーのすべてのクエリは、プレフィックス合計クエリであることを考えると、from
は、常に0
に等しく、だから、子どもへの呼び出しの1つは、些細な答え(0
または既に計算されたsum
)を返す。したがって、バイナリ検索アルゴリズムで2次元ツリーへのクエリO(log N)
を実行する代わりに、このget
クエリと非常によく似た検索のためのアドホック手順を実装することができます。最初に左の子(既に計算されているのでO(1)
が必要です)の値を取得してから、探しているノードが左にあるかどうかを確認する必要があります(この合計は左のサブツリーの葉の数よりも少ない)この情報に基づいて左または右に移動します。このアプローチでは、クエリがO(log^2 N)
時間に最適化されます(今は1つのツリー操作なので)。O((N + Q)log^2 N))
の時間と空間の複雑さをもたらします。
このソリューションは、Q
とN
の両方で十分に高速であるとは確信していませんが、最大で10^5
ですが、さらに最適化されている可能性があります。
私は最初のクエリを処理する前にすべてのクエリを知っていますか?つまり、バッチprocエッセンシャルアルゴリズムは大丈夫です、そして、あなたはオンラインの答えを必要としません – alexeykuzmin0
オフラインアルゴリズムはOKです。 – square1001
それはある種のセグメントツリーの種類の質問ですか? – Arunmu