まず、あなたは尋ねるためにどのような質問を知っているされます:
最も長いシーケンスに上昇し、動的に出発点として1を保持するデータ構造を使用する(シーケンスの斜面に変換する建物の高さ)の長さの。
方法は?セグメントツリー!
このセクションの初めから、この区間2の最大傾斜内のすべての建物はインターバルで見ることができます。私たちは、木の線分に二つのことを維持します。
初期化:
各リーフノードは、ヘッド部から建物の数がこの必ずしもで見ることができる1 、スロープ・ポイントの特定の間隔の最大勾配。
合併時:
1.ば我々はまず、左と右のセクションの最大範囲を見つけることができ、左右のセクションの最大範囲左側の最大範囲よりも小さいが、その後、間隔の左と右のセクションでは、すべての答えを見なければならないので、私たちはすることができます右セクションの右側部分を再帰的に検索します
今のように、我々は範囲の右側のセクションに正しい答えを追加することができます。2.左右の間隔の最大範囲は、左の最大範囲よりも大きい場合には、左側のセクションの元のブロックされた右の部分がブロックされます、ので、我々左セクションの右側部分を再帰的に検索します
時間の複雑さはO(nlog ^ 2n個)です。
#include <ビット/ STDC ++。H> #define INC(I、B)(iは= intを登録する;私は= Bを<; Iは++)のため 名前空間stdを使用。 クラスセグメント{ 公: クラスノード{ 公: ダブルMAXN; すべてをint型。 }ツリー[2000010]。 INTクエリ(INT K、int型のL、int型のR、二重目標){ IF(ツリー[K] .maxn <=目標){ 0を返します。 } もし(1- ==のR){ ツリー[k]は.maxn>目標を返します。 } INT半ば=(L + R)/ 2。 IF(ツリー[K << 1] .maxn <=目標){ クエリを返す(K << 1 | 1、ミッド+ 1、R、ゴール)。 } 他の{ 戻りクエリ(K << 1、L、中間、目標)+ツリー[K] .totツリー[K << 1] .tot。 } } 空隙変化(整数kを、int型のL、int型のR、INTゴール、ダブル値){ IF(L ==目標&& R ==目標){ ツリー[K] .maxn =値。 ツリー[K] .tot = 1。 返します。 } INT半ば=(L + R)/ 2。 IF(目標<= MID)変化(K << 1、L、中間、目標値)。 他の変化(K << 1 | 1、ミッド+ 1、R、目標、値); ツリー[K] .maxn = MAX(ツリー[K << 1] .maxn、ツリー[K << 1 | 1] .maxn)。 ツリー[K] .tot =ツリー[K << 1] .tot +クエリ(K << 1 | 1、中間+ 1、R、ツリー[K << 1] .maxn)。 } } SEG。 N INT、M。 テンプレート<クラスnTの> インラインボイド読み取る(NT&X){ char型のC; 一方、(C = GETCHAR(),! isdigit(c)参照)。 X = C ^ 48。 (C = GETCHAR()、isdigit(c)参照)、一方、X = X * 10 + C-48。 } メインint型() { (n)を読み出します。(m)を読み出します。 INC(I、1、M){ INT X、Y。 (x)を読み出します。(y)を読み出します。 SEG.change(1,1、N、X、(二重)Y / X)。 printf( "%d個の\ n"、SEG.tree [1] .tot)。 } }