https://www.luogu.org/problem/P1908
フェンウィックツリーを使用するのが面倒、ツリーラインを好む(唯一のテンプレートを設定し、ビット操作の本質は理解していない)、という記録フェンウィック木コードがなかったこの質問へのビットを記録している間、彼らは、取得する必要があり、3次元部分順CDQ寝具はフェンウィックツリーの外観を設定します。
問題解決のアイデア:最初、順に元の配列順は、ツリーの配列cに加え、各プレフィックスと数の結果は、現在の番号を逆に求めています。
例えば、データの場合:55,44,22,66,33,11
初期フェンウィックツリーC、クリア。
66-4符号ビットが付加され、配列0,0,0、に添加される1、 0,0、66、それは数以下である前に、逆の数が0、0,0,0フェンウィックツリーCは、 1,0,0;
55-1符号ビットが付加されたアレイに追加され、1、 0,0,1,0,0、それは数より大きくない前55、逆の数が0、フェンウィックツリーCは、1,1,0であります2,0,0;
2ビット目に44を追加し、アレイが1加算される、1、 0,1,0,0、44、それは55よりも大きくなる前に、逆の数が1、配列Cが1,2,0,3木であります、0,0
33-5符号ビットが付加され、アレイ1,1,0,1に追加され、1 0;それは数に逆になる前55,44,66が33よりも大きいを有する3、配列Cは、ツリー2 、0,3,1,1
図22は、アレイは、1,1付加され、3位に加え、1 55,44,66は、それが数に逆になる前に22より大きい有し; 1,1,0 2 C 1、2フェンウィックツリーです、 、1,4,1,2
6〜11は、それがアレイ1,1,1,1,1、に追加され、追加される1、前者が11より大きい、それは数に逆され55,44,22,66,33有する5、フェンウィック木Cを1,2,1,4,1,2として
ピット:後者は、第1の演算の逆対を繰り返さないように、追加に従ってソートされた同じ番号が存在する場合。
書式#include <stdio.hに> する#include <iostreamの> の#include <アルゴリズム> 書式#include <CStringの> 書式#include <math.h>の 書式#include < 文字列 > の#include <マップ> 書式#include <キュー> の#include <スタック> #含む < セット > の#include <CTIME> の#define LL長い長 の#define 0x3f3f3f3f INF CONST ダブル PI = 3.1415926 。 使用して 名前空間はstdを、 const int型 MAXX = 500005 ; 構造体ノード { int型のID; int型のValを; }; ノードA [マックス]; /// オリジナル配列 INT C [マックス]; /// フェンウィックツリー INT N-; BOOL CMP(ノードP1、P2ノード) { IF(P1 == p2.val .val)/// ピット リターン p1.id> p2.id; 戻り p1.val> p2.val; } int型 lowbit(INT X) { 戻り X&( - X); } 無効に追加し(INT X-、INTヴァル)///VALは位置xの値を追加 { ながら(xは<= N + 1)/// X 32005未満が別途要求され、惑星のX = 20000多数これらの入力データの左下を見つけることができません { C [X] + = ヴァル。 X + = lowbit(X); } } int型 SUM(INT X) { int型 RES = 0 ; 一方、(X> 0 ) { RES + = C [X]; X - = lowbit(X); } 戻りRES; } int型のmain()/// P1908 { scanf関数(" %のD "、&N) 以下のために(int型 i = 1 ; iが<= N; iは++ ) scanf関数を(" %のD "、および[I] .val)、[I] .ID = I。 ソート(A + 1、A + N + 1 、CMP)。 LL ANS = 0 。 以下のために(int型私= 1 ; iが<= N; iが++ ) { ANS + = (LL)の和([I] .ID)。 追加([I] .ID、1 )。 } のprintf(" %LLDする\ n" 、ANS); 戻り 0 ; }