タイトル効果:N- $、$ N-1側鎖が$記事になる点があります$。間隔の$ [のL、R] B $所望の距離内で$ A $ランダムに選択された点を求めます。エッジの重みを修正するためにサポートを必要とします。
セクションでは、変更を参照してください、とクエリは、ツリーラインを考えます。
間隔と総距離を考慮してください。
エッジ以来左側とその点での右サイドカバー上の点であるので、総距離をのように表すことができます。
$ \ sum_ {i = L} ^ {R} a_iを×(R-I + 1)*(I-L + 1)$
拡張式場合、$ \和{I = L} {R} a_iを用*与えるために$(RL + RI + R +のIL-iは+ 1-Lを*)
後の時代、私の数によって分類式
$ \ sum_ {iは= L} ^ {R} [I] *(RL + 1 + RL)+ [I] *(R + L)* Iは、[I] * iは$ * +
、発見後ので、追加のレコード$ sum4の$レコードの$ \和I $を更新二悪い計算$更新が簡単にこれらの2つの定数を使用することができたときに私は、私は$ * sum5 $レコードの$ \和答えを計算します。
#include <iostreamの> する#include <cstdioを> する#include <CStringの> する#include <アルゴリズム> の#define半ば(L + R)/ 2 の#define N 100005 40ログの#define の#define lowbit(x)はxと-x の#define MODを998244353 の#define int型、長い長い 名前空間stdを使用。 int型SUM1 [400005]、SUM2 [400005]、SUM3 [400005]、sum4 [400005]、sum5 [400005]、怠惰[400005]。 [400005] int型。 int型ANS1、ANS2、ANS3。 N INT、M。 INT LS(INT X){戻りX << 1;} int型RS(INT X){戻りX << 1 | 1;} ボイドCALC1(今INT) { sum4 [今] = sum4 [(今)LS] + sum4 [RS(現在)]。 sum5 [今] = sum5 [LS(現在)] + sum5 [RS(現在)]。 } ボイドCALC2(今INT) { SUM1 [今] = SUM1 [LS(現在)] + SUM1 [RS(現在)]。 SUM2 [今] = SUM2 [LS(現在)] + SUM2 [RS(現在)]。 SUM3 [今] = SUM3 [LS(現在)] + SUM3 [RS(現在)]。 } ボイドビルドを(int型L、int型のR、今INT) { IF(L == R) { sum4は、[今] Lを=。 sum5 [今] = L * 1。 返します。 } (LS(今)、L、中間)を構築します。 (RS(今)、ミッド+ 1、r)を構築します。 CALC1(今)。 } ボイドワーク(今INT、INTをL、int型のR、int型K) { SUM1 [今] + = K×(R-L + 1)。 SUM2 [今] + = k個の*のsum4 [今]。 SUM3 [今] + = k個の*のsum5 [今]。 怠惰[今] + = K。 } ボイド更新を(int型L、INT R、INT LL、INT RR、整数kを、今INT) { IF(LL <= 1 && R <= RR) { 作業(ここで、L、R、K)。 返します。 } (怠惰[今])であれば { ワーク(LS(今)、L、中間、怠惰[今])。 ワーク(RS(今)、怠惰[今]ミッド+ 1、R)。 怠惰[今] = 0; } (MID> = 11)であれば 更新(LS(今)、L、中間、LL、RR、K)。 IF(中間<RR) 更新(RS(今)、ミッド+ 1、R、RR、LL、K)。 CALC2(今)。 } ボイドクエリ(今INT LをINT、INT R、INT LL、INT RR) { IF(LL <= 1 && R <= RR) { ANS1 + = SUM1 [今]。 ANS2 + = SUM2 [今]。 ANS3 + = SUM3 [今]。 返します。 } (怠惰[今])であれば { ワーク(LS(今)、L、中間、怠惰[今])。 ワーク(RS(今)、怠惰[今]ミッド+ 1、R)。 怠惰[今] = 0; } (MID> = 11)であれば クエリ(LS(今)、L、ミッド、LL、RR); IF(中間<RR) クエリ(RS(今)、ミッド+ 1、R、LL、RR)。 } インラインint型リード() { int型のx = 0、F = 1。 チャーCH = GETCHAR()。 一方、(CH < '0' || CH> '9'){IF(CH == ' - ')は、f = -1; CH = GETCHAR();} 一方(CH> = '0' && CH <= '9 '){X = X * 10 + CH-'0'; CH = GETCHAR();} 戻りのx * Fを、 } (!B)?INT GCD(INT A、INT B){リターンA:GCD(B、%のB);} ()主符号付き { scanf関数( "%のLLDの%のLLD"、&N、&M)。 (1,1、N)を構築します。 以下のために(; I <= M I ++はi = 1からINT) { チャーCH。 cinを>> CH; IF(CH == 'C') { int型のL、R、V。 scanf関数( "%LLD%LLD%LLD"、&L&R&V)。 r--の; 更新(1,1、N、L、R、V)。 他 { int型のL、R。 scanf関数( "%のLLDの%のLLD"、&L&R)。 r--の; ANS1 = ANS2 = ANS3 = 0。 クエリ(1,1、N、L、R)。 INT ANS =(R-L + 1-R * L)* ANS1 +(R + L)* ANS2、ANS3。 INT Q = GCD(ANS、(R-L + 2)*(R-L + 1)/ 2)。 printf( "%LLD /%LLD \ n"は、ANS / Q(R-L + 2)*(R-L + 1)/ 2 / Q)。 } } 0を返します。 }