モノポリーセグメントツリーの半分+ + DFS

https://csustacm.fun/problem/2033

このトピックは非常に簡単ですが、ゲームはあまり馴染みの会長のツリーデータ構造と、として明確でないとき、

だから、バグが登場、木のバグ会長を見つけるのは本当に難しいです。

このトピックでは、最初に見つかったとvalすべての億万長者のDFS +セグメントの木とされます

そして、線分の位置を見つけるために、バイナリツリーを追加します。

書式#include <cstdioを> 
する#include <CStringの> 
の#include <cstdlib> 
書式#include <キュー> 
の#include <アルゴリズム> 
書式#include <iostreamの>
 に#define 0x3f3f3f3f INF
 使用して 名前空間はstdを、
const  int型 MAXN = 1E5 + 10 
typedefの長い 長いLL。
LL [MAXN]、怠惰[MAXN * 4 ]、和[MAXN * 4 ]、フラグ[MAXN * 4 ]。
INT 、N、ヴァル[MAXN]。
ベクター < INT > G [MAXN]。
無効アドオン(INT U、INT V){ 
    G [U] .push_back(V)。
    G [V] .push_back(U)。
} 

ボイド push_down(int型 ID、int型の L、INT R){
     場合(怠惰[ID] == 0のリターン;
    // のprintf( "SSのID =%のDL =%DR =%d個の\ n"、ID、L、R)。
    INT半ば=(L + R)>> 1 もし(フラグ[ID << 1 ]){
         // のprintf( "ID =%のDL =%DR =%d個の\ n"、ID、L、R)。
        和[ID << 1 ] + =(MID - L + 1)* 怠惰[ID]。 
        レイジー[ID << 1 ] + = 怠惰[ID]。
    } 
    であれば(フラグ[ID << 1 | 1 ]){
         // のprintf( "WW ID =%のDL =%DR =%d個の\ n"、ID、L、R)。
        合計[ID << 1 | 1 ] + =(R - MID)* 怠惰[ID]。
        怠惰[ID << 1 | 1 ] + = 怠惰[ID]。
    } 
    怠惰[ID] = 0 ; 
} 

ボイドアップデート1(int型 ID、int型の L、int型の R、int型の POS、int型F){
    もし(POS <L || POS> R)リターン;
    もし(F == 0)フラグ[ID] ++ ;
    そう であれば(F == 1)フラグ[ID] - もし(L == R){ 
        和[ID] = 1 返します
    } 
    push_down(ID、L、R)。
    INT半ば=(L + R)>> 1 もし(POS <= MID)アップデート1(ID << 1 、L、中間、POS、F)。
    他のアップデート1(ID << 1 | 1、ミッド+ 1 、R、POS、F)。 
    の和[ID] =合計[ID <<1 ] +合計[ID << 1 | 1 ]。
} 

ボイドアップデート2(int型 ID、int型の L、int型の R、int型のx、int型のY)
{ 
    // のprintf( "ID =%のDL =%のDR =%DX =%のDY =%d個の\ n"、ID、L、R 、x、y)は、
    もし(X> R || Y <L)のリターン;
    もし(x <= L && Y> = R){ 
        怠惰[ID] + = 1 ; 
        和[ID] + =(R - L + 1 )。
        返します
    } 
    push_down(ID、L、R)。
    int型半ば=(L + R)>> 1 もし(x <= MID)アップデート2(ID << 1 、L、中、X、Y)
    もし(Y> MID)アップデート2(ID << 1 | 1、中間+ 1 、R、X、Y)。
    和[ID] =和[ID << 1 ] +和[ID << 1 | 1 ]。
} 

INTクエリ(INT ID、int型の L、int型の R、int型のPOS)
{ 
    場合(POS <L || POS> R)戻り 0 もし(L == R)戻り和[ID]。
    push_down(ID、L、R)。
    INT半ば=(L + R)>> 1 もし(POS <= MID)戻りクエリ(ID << 1 、L、中間、POS)。
    リターンクエリ(ID << 1 | 1、ミッド+ 1 、R、POS); 
} 

ボイド DFS(INT U、INT PRE){
     // のprintf( "uは=%ダ=%のLLDを\ n"、U、[U])。
    アップデート2(11、nは、1 、[U])。
    アップデート1(11、nは、[U]、0 );
    ためにint型 I = 0、I Gを<U] .size(); iが++ ){
         int型、V = G [U] [I]。
        もし(V ==前)続けます
        DFS(V、U); 
        ヴァル[U] =分(ヴァル[U]、クエリ(11 、nは、[U]));
        // のprintf( "ヴァル[%LLD] =%DV =%d個の\ n"、[U]、ヴァル[U]、V)。
        アップデート1(11、nは、[U]、2 )。
    } 
    アップデート1(11、nは、[U]、1 )。
} 

INT C [MAXN]。

int型lowbit(INT X)
{ 
    戻り X&( - X)。
} 

ボイド更新(int型のx、int型K)
{ 
    一方(X <= N){ 
        C [X] + = K。
        X + = lowbit(X)。
    } 
} 

int型 getsum(INT X)
{ 
    int型 ANS = 0 一方、(X> 0 ){ 
        ANS + = C [X]。
        X - = lowbit(X)。
    } 
    リターンANS; 
} 

int型のmain(){
     int型のX; 
    scanf関数(" %のD "、&N)
    memset(ヴァル、INF、はsizeof (ヴァル))。
    以下のためにint型 i = 1 ; iが<= N; iは++)のscanf(" %dの"、&​​x)は、[X] = I、Gを[I] .clear();
    以下のためにint型 i = 1 ; iがn <; iは++ ){
         int型Uを、V。
        scanf関数(" %d個の%d個"、&​​U&V); 
        (V、U)を追加します。
    } 
    DFS(1、 - 1 )。
    以下のためにint型 I = 1 <; I ++は= N i)があれば(ヴァル[I] = INF)ヴァル[I] => 1 // ( "ヴァル[%のD] =%d個の\ n"は、I、ヴァル[i])とのprintfをするための(iは++; iがn = <I = 1 INT)。
    int型 iは= 1 ; iが<= N iが++ ){
         int型、L = 1、R = N、ANS = 0 一方、(L <= R){
             int型ミッド=(L + R)>> 1 int型 RES =半ば- getsum(中旬)。
            もし(RES> =ヴァル[i])とANS =中間、R =ミッド- 1 リットル=ミッド+ 1 ; 
        } 
        のprintf(" %d個の\ n " 、ANS)。
        アップデート(ANS、1 )。
    } 
    戻り 0 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/EchoZQN/p/11521250.html