問題の意味
$ N $、$ Q $に与えられる数は$のL、R、P、k個の$のいずれかに排他的又は回答の各々を、尋ねる依頼する時間があり、実際の値(すなわち力である)です。小さな$ K $ $の各クエリ、出力$ [のL、R] $ | PA [I] | $。
分析
ツリーの議長は、通常Kの大きいセクションを見つけるために使用され、実際には、その実用的効果は、一定の範囲内の値の数をカウントすることです。そのため、
各お問い合わせは、$ R_L \ simのR_r $ツリーラインに可能な答えを$ xに$に対する答えの半分は$ [PX、P + X] $か$ kの$を検索します。
値上に構築された会長の木、$ 10 ^ 6 $至るまでのデータのこの問題、無ディスクリート(私はしません離散の力によって言葉)
多くの場合、一部のカードを感じ、32倍、55倍のスペースは、(ああ、なぜ)上で64倍に変更し、TLEあります
#include <ビット/ STDC ++ H.> 使用して 名前空間STD; のconst int型 MAXN 1E5 + = 100 ; INT N-、M; // INT A [MAXN]; // INT RT [MAXN]、LC [<< MAXN 5] RC [MAXN << 5]、SUM [MAXN << 5]; // RT:ルートノードLC / RCの異なるバージョン:息子は左右息子(パブリック)合計:及び(パブリック)は int型 RT [MAXN]、LCを【MAXN * 64 ]、RC [MAXN * 64 ]、SUM [MAXN * 64 ]; int型 node_cnt; // ノードの総数、pnt_disc:Bに対応するデジタル値 のint =範囲1000000 ; // データの範囲は、セグメントツリーはの大きさである ボイドビルド(int型&last_node、int型の L、int型R) { last_node = ++ node_cnt。 和[last_node] = 0 ; もし(L == R)の リターン; INT半ば=(L + R)>> 1 。 (LC [last_node]、L、中間)を構築します。 (RC [last_node]、中間ビルド + 1 、R)。 } int型(変更INT pre_rt、INT V、INTを L、INT R) { int型 new_rt = ++ node_cntと、 LC [new_rt] =LC [pre_rt]。 RC [new_rt] = RC [pre_rt]。 和[new_rt] =和[pre_rt] + 1 。 INT半ば=(L + R)>> 1 。 もし(L == R) 戻りnew_rt。 もし(MID> = V)LC [new_rt] = 修正(LC [new_rt]、V、L、MID)。 他の RC [new_rt] =変更(RC [new_rt]、V、中間+ 1 、R)。 リターンnew_rt。 } // 查询[QL、QR]中不同元素个数 INTクエリ(INT RT1、INT RT2、INT QL、INT QR、INT L、INT R) { // のprintf( "RT1:%D RT2:%のDK:%のDL:%のDRた:%d"、RT1、RT2、K、L、R)。 もし(QL <= 1 && R <= QR) 戻り和[RT2] - 和[RT1]。 INT半ば=(L + R)>> 1 。 int型 ANS = 0 ; もし(QL <= MID)ANS + = クエリ(LC [RT1]、LC [RT2]、QL、QR、L、MID)。 もし(QR> MID)ANS + =クエリ(RC [RT1]、RC [RT2]、QL、QR、中間+ 1 、R)。 戻るANSを。 } ボイドprint_debug() { のprintf(" node_cnt:%Dを\ n " 、node_cnt)。 用(int型 I = 0 ; I <= node_cnt iが++ ) のprintf(" :%D RC:%dの合計%Dを\ n%d個のLC " 、I、LC [i]は、RC [i]は、和[I ]); } int型のmain() { int型のT。 scanf関数(" %のD "、&T)。 一方、(T-- ) { scanf関数(" %d個の%のD "、&N、&M)。 node_cnt = 0 ; (RT [ビルド0 ]、1 、範囲)。 以下のための(INT I = 1 ; I <= N; I ++ ) { int型TMP; scanfの(" %のD "、&TMP); RT [I] =修正(RT [I- 1 ]、TMP、1。 、レンジ); // 唯一のバージョンに基づいて改変 } INT ANS = 0 ; のため(int型 I = 0 ; iがm <; I ++は) { int型のLは、R、P、K、 scanfの(" %D%D%D%D "、&Lは、R&、&P、およびK); L^ = ANS; R ^ =のANS。 P ^ =のANS; K ^ =のANS。 場合(L> R)スワップ(L、R)。 INTは L = 0、R =レンジ。 // 一方(L <= R) { int型 M = Lの+(RL)/ 2 。 もし(クエリ(RT 1- [ 1 ]、RT [R]、MAX(1、PM)、分(P + M、範囲)、1、範囲)> = K) { ANS = M。 R = M- 1 。 } 他の L = M + 1 ; } のprintf(" %d個の\ n " 、ANS)。 } } } [クリップボードにコピー]、[ファイルに保存]
参考リンク:
1. https://blog.csdn.net/birdmanqin/article/details/97964662