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