水問題とKeduo李ツリー。
コードは次のように実装されています。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 #defineは長いlong int型 の#define ITセット<ノード> ::イテレータ の#define(; I '=(B)は、i ++は、I =(A)がINTレジスタ)のための担当者(I、B)CONST INT MAXN = 1E5 +を5 ; INTのN、M。 INT [MAXN]。構造体ノード{ int型のL、R。 変更可能なブールV; ノード(INT L、int型の R = - 1、INT V = 0 ):L(L)、R(R)、V(V){} ブール演算子(< CONSTノード&O)のconst { 戻り L < OL。 } }。 セット <ノード> S。 INT MAX(int型、int型 B){ 戻り > bは?A:B;} intです読み出す(){ int型のx = 0、フラグ= 0 。 CHAR CH = ' ' ; しばらく(!CH = ' - ' &&(CH < ' 0 ' || CH> ' 9 '))CH =getchar関数(); もし(CH == ' - ' ){ フラグ = 1 。 CH = GETCHAR()。 } 一方、(CH> = ' 0 ' && CH <= ' 9 ' ){ X =(X << 1)+(X << 3)+(CH ^ ' 0 ' )。 CH = GETCHAR()。 } を返すフラグ?- X:X; } ITを分割(int型のPOS){ ITを= s.lower_bound(ノード(POS))。 もし(それ= s.end()&& IT-> L == POS!)を返すことを。 それは - 。 int型 L = IT-> L、R = IT-> R、V = IT-> V。 s.erase(それ)。 s.insert(ノード(L、POS - 1 、V))。 戻りs.insert(ノード(POS、R、V))を最初。 } ボイド割り当て(int型 L、INT R、INT ヴァル){ IT ITR =スプリット(R + 1)、ITL = スプリット(L)。 s.erase(ITL、ITR)。 s.insert(ノード(L、R、ヴァル))。 } のボイドrever(int型 L、int型r)は{ IT ITRが分割=(R + 1)、ITL = スプリット(L)。 しばらく(!ITL = ITR){ ITL - > V ^ = 1 ; ITL ++ ; } } int型の和(INTの L、INT R){ IT ITR =スプリット(R + 1)、ITL = スプリット(L)。 int型 ANS = 0 ; しばらく(ITL!= ITR){ ANS + = itl-> V?itl-> R - itl-> L + 1:0 ; ITL ++ ; } 戻りANS。 } INT con_sum(INT L、INT R){ IT ITR =スプリット(R + 1)、ITL = スプリット(L)。 int型 ANS = 0、今= 0 ; 一方、(!ITL = ITR){ 場合(!(itl-> V)){ ANS = MAX(ANS、今)。 今 = 0 ; } そう今+ = itl-> R - itl-> L + 1; ITL ++ ; } 戻りMAXを(ANS、今)。 } ボイド書き込み(INT X){ 場合(X < 0 ){ のputchar(' - ' )。 X = - X。 } 場合(X> 9)書き込み(X / 10 )。 putchar(Xの%10 + ' 0 ' )。 } )(主符号付き{ N、M =)(=読み取り)(読み取ります。 担当者(I、0、N -1 ){ [I] = (読み取り) s.insert(ノード(I、I、[I]))。 } s.insert(ノード(N、N、0 )); 担当者(I、1 、M){ int型のL、R、選びます。 オプト =読み取る()、L =読み取る()、R = 読み取り()。 もし割り当てる(L、R、(OPT!)0 ); そう であれば(OPTの== 1)を割り当てる(L、R、1 )。 そう であれば(OPT == 2 )rever(L、R)。 それ以外の 場合(オプト== 3){ 書き込み(合計(L、R))。 printf(" \ nを" ); } 他{ ライト(con_sum(L、R))。 printf(" \ nを" ); } } 戻り 0 。 }