セグメントツリー[] codeforces - 438Dと子の配列(断面係数)
タイトル効果:
1セグメント間隔加算モジュロ2. 3.単一点更新:3つの操作があります
問題解決の分析:
主な考慮事項は、間隔モジュロ演算に対処する方法では、常に非常に一般的な剪定、メンテナンス間隔の最大値は、最大値が型よりも大きいときにのみ、存在し、暴力的なモジュロ時刻のすべてのモジュロ数を持つことはできません我々はそうでない場合は終了し、剰余演算を継続するために降りてくる番号。非常に明白な結論はそれぞれモジュロ番号可能があるので、モジュロ後、それは必然的にその数$ \の{2} $のFRAC以下になる{1}。だから、それぞれのログ番号は$ $成形回までとなり、間隔を法の複雑さは$ O(nlogn)$です。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 テンプレート <型名T> インラインボイドリード(T&X){ X = 0。int型、F = 1。チャー CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ')、F = - 1。CH = GETCHAR()。} 一方、(CH> = ' 0 ' && CH <= '){X = X * 10 + CH- ' 0 '。CH = GETCHAR()。} 、X * = F。 } の#define LSON RT << 1、L、中間 の#define Rson RT << 1 | 1、中間+ 1、R の#defineっ長い長 の#define REP(I、S、T)(I = Sをint型のために、私<= T; iは++)のconst int型 N = 1E5 + 5 。 LLのMX [N << 2 ]、合計[N << 2 ]、[N]。 INTのN、M。 インラインボイド押し上げ(int型RT){ MX [RT] = MAX(MX [RT << 1 ]、MX [RT << 1 | 1 ])。 合計[RT] =合計[RT << 1 ] +合計[RT << 1 | 1 ]。 } ボイドビルド(INT RT、INT L、INT R){ 場合(L == R){ MX [RT] =和[RT] = [L]を、 返します。 } INT半ば= L + R >> 1 。 (LSON)を構築;(Rson)を構築。 突き上げ(RT)。 } ボイド UP1(INT RT、INT L、INT R、INT LOC、INTヴァル){ // 单点更新 する場合(L == R){MX [RT] =和[RT] =ヴァル。返します。} INT半ば=(L + R)>> 1 。 もし(LOC <= MID)UP1(LSON、LOC、val)で、 他UP1(Rson、LOC、val)で、 突き上げ(RT)。 } ボイド UP2(INT RT、INT L、のint R、int型の L、INT R、INT MD){ 場合(MD> MX [RT])のリターン; もし(L == R){ 和[RT]%= MD; MX [RT] = 和[RT]。 返します。 } INT半ば=(L + R)>> 1 。 もし(L <= MID)UP2(LSON、L、R、MD)。 もし(R> MID)UP2(Rson、L、R、MD)。 突き上げ(RT)。 } LLクエリ(INT RT、INT L、のint R、int型の L、INT R){ 場合(L <= 1 && R <= R)戻り和[RT]。 INT半ば=(L + R)>> 1 。 LL ANS = 0 。 もし(L <= MID)ANS + = クエリ(LSON、L、R)。 もし(R>中旬)ANS + =クエリ(Rson、L、R)。 戻るANSを。 } int型のmain(){ (n)を読み出す;(m)を読み出します。 REP(I、1 、n)を読み出す([I])。 ビルド(1、1 、N) 一方、(M-- ){ int型のOP、READ(OP)。 もし(OPの== 1 ){ int型のL、R(l)を読み出す;(r)を読み取ります。 printf(" %LLDする\ n "、クエリ(1、1 、N、L、R))。 } そう であれば(オペアンプ== 2 ){ int型L、R、MD;(l)を読み出す;(r)を読み出す;(MD)を読み取ります。 UP2(1、1 、N、L、R、MD)。 } 他{ int型のLOCは、C(LOC)を読み出す;(C)を読み取ります。 UP1(1、1 、nは、LOC、C)。 } } }