動的セグメントツリー分割離れ点+ -tree鎖BZOJ4999

それぞれの色は、DFSセグメントツリーノードとして、内部指図セグメントツリーを開き、右の値は出現、メンテナンス間隔、ツリー行の数を表します。

書式#include <iostreamの> 
書式#include <stdio.hに> 
する#include < 文字列の.h> 
の#include <アルゴリズム> 
書式#include <マップ>
 使用して 名前空間はstd;
const  int型 MAXN = 2E5 + 6 構造体のエッジは{
    int型、隣。
} E [MAXN * 2 ]。
構造体ノード{
   int型のL、R。
  int型のw; 
}ツリー[MAXN * 50 ]。
int型のヘッドは、[MAXN]、[MAXN] SIZ、トップ[MAXN]、息子[MAXN]。
INT D [MAXN]、FA [MAXN]、ID [MAXN]、RK [MAXN]、DFN [MAXN]、[MAXN] C。
INTのN、M、UU、VV、TOT、CNT。
int型RT [MAXN]。
マップ < int型int型 > のp;
ボイド追加(int型のx、int型のY){ 
    E [ ++ CNT] .next = 頭部[X]。
    E [CNT] .TO = Y。
    ヘッド[X] = CNT。
} 
ボイド DFS1(INT U、INT F、int型の深さ){ 
   D [U] = 深度。
   FA [U] = F。
   [U] SIZ = 1 以下のためのint型I =ヘッド[U]; I; I = E [I] .next){
       int型、V = E [I] .TO。
      もし(vは== f)を続けます
      DFS1(V、U、深さ + 1 )。
      SIZ [U] + = SIZ [V]。
      もし(SIZ [V]> SIZ [息子[U])
        息子[U] = V。
   } 
} 
ボイド DFS2(int型 U、int型T){ 
   トップ[U] =のT。
   DFN [U] = ++ CNT。
   もし(!息子[U])
      のリターン; 
   DFS2(息子[U]、T); 
   以下のためのint型 I =ヘッド[U]; I; I = E [I] .next)
   { 
       int型、V = E [I] .TO。
       もし(!!V =息子[U] && V = FA [U])
         DFS2(vは、v)は、
   } 
} 
ボイド変更(INT&X、int型の L、int型の Rは、int型 POSを、INT W)
{ 
    もし X = ++ TOT(X!)。ツリー[X] .W + = W。
    もし(L == R)のリターン;
    INT半ば=(L + R)>> 1 もし(POS <= MID)変更(ツリー[X] .L、L、中間、POS、W)。
    それ以外の変更(木[X] .R、ミッド+1 、R、POS、W)。
} 
INTクエリ(int型のx、int型の L、int型の R、int型の L、INT R){
     場合(!(ツリー[X] .W)||(X))戻り 0 ;
    もし   (L <= 1 && R <= R){
          戻りツリー[X] .W。
    } 
    INT半ば=(L + R)>> 1 int型 ANS = 0 ;
    もし(L <= MID)ANS + = クエリ(ツリー[X] .L、L、中、L、R)。
    もし(R> MID)ANS + =クエリ(ツリー[X] .R、中間+ 1 、R、L、R)。
    戻るANSを。
}
INT qryRange(int型のx、int型の Y、int型K){
    int型 RES = 0 一方(上部[X] =!トップ[Y]){
       場合(D [トップ[X] < D [トップ[Y])スワップ(X、Y)
      RES + =クエリ(RT [K]、1 、nは、DFN [トップ[X]、DFN [X])。
      X = FA [TOP [X]]。
   } 
   もし、(D [Y]> D [X])スワップ(X、Y)
   RES + =クエリ(RT [K]、1 、nは、DFN [Y]、[X] DFN)。
   リターンのres; 
} 
int型のmain(){
   int型の和= 0 、Q。
  同時に(〜のscanf(" %D%dの"、&​​N&Q)){ 
      CNT = 0 
      合計 = 0 ;
      以下のためにint型 i = 1 ; iが<= N; iが++ ){ 
         scanf関数(" %のD "、&C [I])。
      } 
      のためのint型 i = 1 ; iが<= N iが++ ){ 
        scanf関数(" %D%dの"、およびUU、&VV)。
        追加(UU、VV); 
        (VV、UU)を追加します。
      } 
      CNT = 0
      DFS1(101 )。
      DFS2(11 )。
      TOT = 0 ;
      以下のためにint型 i = 1 ; iが<= N; iが++ ){
         場合(P [C [I]] == 0 ){ 
            P [C [I] = ++ 和。
        } 
        変更(RT [P [C [I]]]、 1、nは、DFN [i]は、1 )。
      } 
      チャー TMP [ 3 ]。
      int型V、W、Uを。
      しばらく(q--){
         scanf関数(" %sの" 、TMP)。
         もし(TMP [ 0 ] == ' C ' 
         { 
             scanf関数(" %d個の%のD "、&​​U、&W)。
             変更(RT [P [C [U]]]、1、nは、DFN [U]、 - 1 )。
             もし(!P [W])P [W] = ++ 合計。
             変更(RT [P [] W]、1、nは、[U] DFN、1 )。
             C [U] = W。
         } { 
             scanf関数(" %D%D%D "、&​​U&V、& W)
             もし(!P [W])のprintf(" 0 \ N " );
             のprintf(" %d個の\ n " 、qryRange(U、V、P)[W])。
         } 
      } 
  } 
  戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/bluefly-hrbust/p/11774637.html