タイトル説明:https://www.luogu.org/problemnew/show/P3391
分析:ここではスプレイの重量のビューの主なポイントについて話をします。まず、行きがけのスプレイは常に同じなので、先行順スプレイの考えは元の配列の位置を表すことがわかりました。それでは、どのようにそれを達成するには?位置が成果に重量であるとき私たちはまだ始まったばかりの成果を必要としています。ちょうどオーダースプレイトラバーサル順に位置に貢献するために、別の言い方をすれば。だから、実際には、風雲はどのコースをスプレイ重みの元の配列の数は、唯一のちょうどその時の方法の変更の成果の成果を始めていますさ。大きな広がりを満たしていないスワップはまだ右の小さな自然を残し、後にそう何人かの学生は、頼むかもしれませんか?確かにああ満足していません。一部の学生はそれではありませんスプレイの性質に満足していた、R + 1がL-1に行く息子の右に回転させることができるようになりますことを確認する方法を、別の質問を求めることができますか?注、スプレイ回転操作は、重量ポイントとは何の関係もありません、それは関係を構築するためにどのようにスプレイでちょうど木です。
コード(原点の元の配列)を取り付けます。
書式#include <cstdioを> する#include <アルゴリズム> 使用して 名前空間はstdを、 const int型 MAXN = 100005 ; INTのN、M。 int型のルート。 構造体ノード{ int型のサイズ、息子[ 2 ]、ヴァル、FA、タグ。 }ノード[MAXN]。 int型 ndnum = 0 ; int型の起源[MAXN]。 int型のチェック(int型X){ 戻り X ==ノード[ノード[X]の.Fa] .son [ 1 ]。 } ボイド更新(INT X){ ノード[X] .size =ノード[ノード[X] .son [0 ]]サイズ+ノード[ノード[X] .son [ 1 ]サイズ+。1 。 } ボイド回転(INT X){ int型、Y =ノード[X]の.Fa、Z =ノード[Y]の.Fa、D =チェック(X)、XX =ノード[X] .son [D ^ 1 ]。 ノード[Y] .son [D] = XX、ノード[XX]の.Fa = Y。 ノード[Z] .son [チェック(Y)] = xと、ノード[X]の.Fa = Z。 ノード[X] .son [D ^ 1 ] = Y;ノード[Y]の.Fa =のX。 アップデート(Y)、更新(X)。 } ボイドスプレイ(INT X、INT =まで0 ){ 一方(ノード[X]の.Fa!= に){ int型Y =ノード[X]の.Fa、Z = ノード[Y]の.Fa。 もし(Z =!へ){ 場合(チェック(X)== チェック(Y))が(y)を回転させます。 他の回転(x)は、 } 回転(X) } もしルート=の(に!)X。 } ボイドインサート(INT X){ int型 CUR =ルート、F = 0 。 一方、(!CUR &&ノード[CUR] .val = X){ F = CUR。 CUR =ノード[CUR] .son [X> ノード[CUR] .val]。 } CUR = ++ ndnum。 もし(f)はノード[F] .son [X>ノード[F] .val] = CUR。 ノード[CUR] .size = 1 ;ノード[CUR] .TAG = 0 。 ノード[CUR] .son [ 0 ] =ノード[CUR] .son [ 1 ] = 0 。 ノード[CUR] .val = xで、ノード[CUR]の.Fa = F。 スプレイ(CUR)。 } ボイドプッシュダウン(int型CUR){ 場合(ノード[CUR] .TAG){ ノード[ノード[CUR] .son [ 0 ]タグ^ = 1 ; ノード[ノード[CUR] .son [ 1 ]タグ^ = 1 ; ノード[CUR] .TAG = 0。 スワップ(ノード[CUR] .son [ 0 ]、ノード[CUR] .son [ 1 ])。 } } int型 k番目(INT K){ int型 CUR = ルート。 一方、(1 ){ プッシュダウン(CUR)。 もし(K <=ノード[ノード[CUR] .son [ 0 ]]サイズ。) CUR =ノード[CUR] .son [ 0 ]。 他{ K - =ノード[ノード[CUR] .son [ 0 ]のサイズ+。1 。 もし(!k)の戻りCUR。 CUR =ノード[CUR] .son [ 1]; } } } ボイドリザーブ(int型 L、INT R){ L = k番目(1- 1); R = k番目(R + 1 )。 スプレイ(L)、スプレイ(R、L)。 ノード[ノード[ノード[ルート] .son [ 1 ]の息子[ 0 ]タグ^ = 1 ; } ボイド書き込み(INT CUR){ プッシュダウン(CUR)。 もし(ノード[CUR] .son [ 0 ])、ライト(ノード[CUR] .son [ 0 ])。 もし(ノード[CUR] .val> 1つの &&ノード[CUR] .val <N + 2)のprintf("%のD 」、原点[ノード[CUR] .val- 1 ]); 場合(ノード[CUR] .son [ 1 ])、ライト(ノード[CUR] .son [ 1 ]); } int型のmain(){ scanf関数(" %dの%のD "、&N、&M) のための(int型 I = 1を iが<= N; iが++)のscanf(" %dの"、&;原点[i])と するために(int型 i = 1 ; iが< = N + 2、iが++ )(i)を挿入する。 ために(int型 I = 1 ; I <= M; iが++ ){ int型のL、R。 scanf関数(" %dの%のD "、&L&R)。 リザーブ(L + 1、R + 1 )。 } 書き込み(ルート)。 リターン 0 ; }