まあスプレイとの最初の維持
クエリがルートに対応するノードを置いたときに続いて、左部分木のサイズがランクされています
その後、間隔を反転することを計画
書式#include <cstdioを> する#include <cmath> の#include <CStringの> の#include <cstdlib> 書式#include <iostreamの> の#include <アルゴリズム> 書式#include <キュー> の#include <スタック> 使用して 名前空間はstd; 構造体ノード { int型V、NUM。 フレンドブール 演算子 < (ノードA、ノードB) { 戻り AV == BV a.num <b.num:AV < BV。 } } P [ 100005 ]。 INTの CH [ 100005 ] [ 2 ]。 int型の SIZ [ 100005 ]。 INT [ 100005 ]。 INT [F 100005 ]。 int型 FL [ 100005 ]。 int型の腐敗。 int型のn; ボイドプッシュダウン(INT X) { 場合(FL [X]) { スワップ(CH [CH [X] [ 0 ] [ 0 ]、CH [[x]はCH [ 0 ] [ 1 ])、FL [CH [ X] [ 0 ]] ^ = 1 ; スワップ(CH [CH [X] [ 1 ] [ 0 ]、CH [CH [X] [ 1 ] [ 1])、FL [CH [X] [ 1 ] ^ = 1 ; FL [X] = 0 ; } } ボイド更新(INT X) { SIZ [X] = SIZ [CH [X] [ 0 ] + SIZ [CH [X] [ 1 ]] + 1 。 } ボイド回転(INT X) { int型、Y = F [X]、Z = F [Y]、K =(CH [Y] [ 1 ] == X) CH [Z] [CH [Z] [ 1 ] == Y] = xで、[X] = F Z。 CH [y]は[K] = CHを[X] [K!]、F [CH [X] [] kは!] = yと; CH [X] [!K] = Y、F [Y] = X。 アップデート(Y)、更新(X)。 } 無効 dfs_pushdown(int型x)は { 場合(!x)が復帰。 dfs_pushdown(F [X])。 プッシュダウン(X)。 } ボイドスプレイ(int型のx、int型ED) { dfs_pushdown(X)。 一方、(![X] = F ED) { int型、Y = F [X]、Z = F [Y]。 もし(!Z = ED) { もし、((CH [Y] [ 1 ] == X)^(CH [Z] [ 1 ] == Y))に回転(X) そうでなければ(Y)を回転させます。 } 回転(X) } もし(!ED)腐れ=のX。 } int型 get_pos(int型のx、int型K) { プッシュダウン(X)を、 もし(SIZ [CH [X] [ 0 ]> = K)戻り get_pos(CH [X] [ 0 ]、K)。 そう であれば(SIZ [CH [X] [ 0 ] + 1 <k)の戻り get_pos(CH [X] [ 1 ]、K- 1 -siz [CH [X] [ 0 ]])。 他の リターンX; } int型のスプリット(int型の L、 int型R) { INT V1 = get_pos(腐敗、1- 1)、V2 = get_pos(腐敗、R + 1 )。 スプレイ(V1、0 )、スプレイ(V2、V1)。 戻り CH [V2]を[ 0 ]。 } ボイド rever(int型 L、int型R) { int型、P = スプリット(L、R)。 スワップ(CH [P] [ 0 ]、CH [P] [ 1 ])、FL [P] ^ = 1 ; } INT buildtree(INT L、のint R、int型のFA) { int型ミッド=(L + R)>> 1 。 、F [中間] = [FA]。 FL [中間] = 0 ; もし(L == R){FL [中間] = 0 ; [中間] [CH 0 [中間] [] CHを= 1 ] = 0を SIZ [中間] =。1 ; 戻り[中間]を;} もし(L <MID)CH [中間] [ 0 ] = buildtree(L、ミッド1 、MID)。 他の CH [[中期]] [ 0 ] = 0 ; もし(R> MID)CH [中間] [ 1 ] = buildtree(MID + 1 、R、MID)。 他の CH [[中期]] [ 1 ] = 0 ; アップデート([中間])。 戻る[中期]。 } INTクエリ(INT X) { スプレイ(X、0 ); 戻り [[X] [CH SIZを0 ]]。 } int型のmain() { ながら(1 ) { scanf関数(" %のD "、&N) もし(!n)のリターン 0 ; 以下のために(int型 i = 1 ; iが<= N; iは++)のscanf(" %dの"、&Pを[I] .V)、P [i]は.num = I。 ソート(P + 1、P + N + 1 )。 以下のために(int型 i = 1 ; iが<= N; iは++)[Pを[I] .num + 1 ] = I + 1 。 [ 1 ] = 1、[N + 2 ] = N + 2 。 腐敗 = buildtree(1、N + 2、0 ); 以下のために(int型 i = 1 ; iが++; iが<= N ) { int型 T =クエリ(iは+ 1 )。 もし(T>ⅰ)rever(I + 1、T + 1); printf(" %dの" 、T)。 } のprintf(" の\ n " ); } 戻り 0 。 }