問題の解決策
第一の方法:注文アレイツリー記録のスタックで[]の要素は、xの値の数は、[X]スタックツリーです。フェンウィックツリーのメンテナンスツリー[]、その後、バイナリ検索。
第二の方法:暴力を探し、次に、ブロック、一定の長さの間隔の単位を使用して、スタック内の値の数を記録し、そして。
コード
// 树状数组+二分
の#include <ビット/ STDC ++ H> 使用して名前空間STDを、
const int型 MAXN = 100010 ;
int型のツリー[MAXN]。
スタック < 整数 > STA;
空アップデート(int型のp、int型ワット)。
int型の合計(int型P);
INT のmain()
{ int型N、W、左、右、中、K。
文字列のOP;
scanf関数(" %のD "、&N)
一方、(N-- )
{
CIN
>> オペアンプ;
もし(OP [ 1 ] == ' U ' )
{
scanf関数(" %のD "、&W)。
sta.push(W)。
(W更新1 )。
}
他
{
場合(sta.size()< 1)のprintf(" 無効\ n " );
そう であれば(OP [ 1 ] == ' O ' )
{
のprintf(" %D \ n "、sta.top())。
アップデート(sta.top() - 1 )。
sta.pop();
}
他
{
左 = 0 ;右= MAXN; K =(sta.size()+ 1)/ 2 。
一方(左<= 右)
{
半ば =(左+右)/ 2 。
もし(和(MID)> = k)の右=半ば1 。
他に 左=ミッド+ 1 ;
}
のprintf("%D \ n " )左;
}
}
}
システム(" 一時停止" );
戻り 0 ;
}
ボイド更新(int型 P、INT W)
{
ため(; P <MAXNあり; p + = P&( - P))
ツリー[P] + = W;
}
int型の和(INT P)
{
int型 ANS = 0 ;
のための(; P> 0 ; P - = P&( - P))
ANS + = ツリー[P];
リターン年;
}
// 分块
の#include <ビット/ STDC ++ H> 使用して名前空間STDを、
const int型 MAXN = 100010、BLOCK_SIZE = 367 ;
INT CNT [MAXN]、ブロック[ 280 ]。
スタック < 整数 > STA;
無効 PUSH_POP(int型のインデックス、int型のV)。
int型の検索(int型k)は、
int型のmain()
{ int型のn、wは。
文字列のOP;
scanf関数(" %のD "、&N)
しばらく(N -
)
{
CIN >> OP。
もし(OP [ 1 ] == ' U ' )
{
scanf関数(" %のD "、&W)。
sta.push(W)。
PUSH_POP(W 1 )。
}
他
{
場合(sta.size()< 1)のprintf(" 無効\ n " );
それ以外の 場合(OP [ 1 ] == ' O ' )
{
のprintf("%dの\ n " 、sta.top())。
PUSH_POP(sta.top() - 1 )。
sta.pop();
}
他 のprintf(" %dの\ n "、検索((sta.size()+ 1)/ 2 ))。
}
}
システム(" 一時停止" )。
リターン 0 ;
}
ボイド PUSH_POP(int型のインデックス、INT V)
{
CNT [インデックス] + = V。
ブロック[インデックス/ BLOCK_SIZE] + = V。
}
INT検索(int型K)
{
int型の和= 0、iが= 0 、インデックスを、
一方、(和+ブロック[I] < k)の
和 + =ブロック[I ++ ]。
インデックス = BLOCK_SIZE * 私は、
一方、(1 )
{
場合(和+ CNT [インデックス]> = K)リターン指数。
他の合計+ = CNT [インデックス]、インデックス++ ;
}
}