もし$ C = 0 $(すなわち、一つだけの色)をLCT aを開き、ノードの次数を維持するために、だから今$ C <10 $、一緒に維持して、$ LCTツリーを$のC + 1を開く考えます。それを見つけるためにマップ上に直接サイド。
書式#include <cstdioを> する#include <マップ> 使用して 名前空間はstdを、 const int型の N = 10005 ; チャーはrB [ 1 << 21 ]、* rSを、* をrT。 インラインチャー GC(){ 戻り rSを==をrT &&(RT =(RS = rBの)+関数fread(RB、1、1 << 21、STDIN)はRS == RT)EOF:* rSを++ ;} インラインint型RD( ){ チャー C = GC()。 一方、(C < 48 || C> 57)C = GC()。 int型のx = C&15; 用(C = GC(); C> = 48個の && C <= 57、C = GC())x =(x << 3)+(X << 1)+(C&15 )。 リターンのx; } INT ヴァル[N]、ST [N]、SL。 構造体の縁{ int型Uを、V。 エッジ(){} エッジ(int型のx、int型のY){ 場合(X <Y){U = X; V = Yであり;} 他 {UはYを=; V =のX;} } インラインブール 演算子 <(constのエッジ&B )CONST { リターンU <BU || U == BU && V < BV;} }。 地図 <エッジ、INT > F。 構造体LCT { INT MAXN [N]、F [N]、CH [N] [ 2 ]、D [N]を。 BOOL タグ[N]。 インラインブール NRT(INT O){ 戻り [[[O] F] CH 0 [[[O] F]] == O || CH 1 ] == O;} インラインブール DIR(INT O){ 戻り CH [ F [O]] [ 1 ] == O;} インラインボイドフリップ(INT O){ もし(O){ int型 T = CH [O] [ 0 ]; CH [O] [ 0 ] = CHを[O] [ 1 ]; CH [O] [ 1 ] = T。 タグ[O] ^ = 1 ; } } インラインボイド押し上げ(INT O){ MAXN [O] = MAXN [CH [O] [ 0 ]]> MAXN [CH [O] [ 1 ] MAXN [CH [O] [?0 ]:MAXN [ CH [O] [ 1 ]。 もし(ヴァル[O]> MAXN [O])MAXN [O] = valの[O]。 } インラインボイド PUSHD(INT O){ もし{([の]バナー) フリップ(CH [の] 0 ]);フリップ(CH [A] [ 1 ])。 バナー[T] = 0 ; } } インラインボイド腐朽(int型D){ int型 4 = F [t]を。 ブール D = DIR(D)。 V [T] = F [4]。 強制(NRT(4))CH [F [第4] [DIR(4つ)= 。 強制(CH [4] [D]をCH = [A]、[D ^ 1 ])V [CH [4] [D] = ; 4 V [CH [A]、[D ^ 1 ] = 4個] = 。 突き上げ(4つ)。 } インラインボイドスプレイ(INT O){ int型 K = ST [SL = 0 ]は、= Oと、 一方、(NRT(K)){K = F [k]は、ST [++ SL] = K;} ながら(SLは> = 0)PUSHD(ST [sl-- ])。 用(腐敗(O); NRT(O))であれば((DIR(O)^ DIR([O] F))?(NRT(F [O]))腐敗:[O] F O) 突き上げ(O) } インラインボイドアクセス(INT X){ ため(int型、Y = 0 ; X; X = F [Y = X]){ スプレイ(X)。 CH [X] [ 1] = Y。 突き上げ(X)。 } } インラインINT findrt(INT X){ アクセス(X)、スプレイ(X)。 ため(PUSHD(x)は、をch [X] [ 0 ]; PUSHD(X))×= CHを[X] [ 0 ]。 スプレイ(X)。 リターンのx; } インラインボイド makert(INT X){ アクセス(X)、スプレイ(X)。 フリップ(X)。 } インラインボイドリンク(int型のx、int型のY){ makert(X)。 ++ D [X]; ++ D [Y]。 F [X]= Y。 } インラインボイドカット(int型のx、int型のY){ makert(x)は、アクセス(Y)、スプレイ(X)。 [X] --d; - D [Y]を。 CH [X] [ 1 ] = F [Y] = 0 。 突き上げ(X)。 } } LCT [ 10 ]。 INT {main()の 整数 N = RD()、M = RD()、C = RD()、Q = RD()、I、J、U、V、W、P、選びます。 用(i = 1 ; iは= N <; ++ I){ ヴァル[I] = RD()。 用(J = 0 ; J <C; ++ j)はLCT [J] .maxn [I] = valの[I]。 } 一方、(M-- ){ U = RD(); V = RD(); W = RD()。 LCT [W] .link(U、V)。 F [エッジ(U、V)] = W。 } 一方(q-- ){ OPT = RD(); U = RD(); V = RD()。 もし(!OPT){ valの[U] = V; 用(i = 0 ; iはCを<; ++ I)LCT [I] .splay(U)。 } そう であれば(OPTの== 1 ){ W = RD()。 もし(f.find(エッジ(U、V))== f.end()){プット("そのようなエッジありません。"); 続ける ;} // 用或者カウント、不要用[]見つける P = F [エッジ(U、V)]; 場合(==のP W){プット(" 。成功"); 続ける;} もし( .D [U]> = [W] LCT 2 || LCT .D [W] [V]> = 2){プット(" エラー1. " ;)継続;} LCT [W] .makert(U)。 もし(LCT [W] .findrt(V)== U){プット(" エラー2 "); 続ける;} プット(" 成功。"); LCT [P] .cut(U、V); LCT [W] .link(U、V)。 F [エッジ(U、V)] = W。 } そう であれば(OPTの== 2 ){ LCT [U] .makert(V)。 もし(!LCT [U] .findrt(ワット= RD())= v)のプット(" -1 " ); 他のprintf(" %d個の\ n " 、LCT [U] .maxn [V])。 } } 戻り 0 。 }