luogu P2221 [HAOI2012]高速道路

タイトル効果: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を返します。
}

  

おすすめ

転載: www.cnblogs.com/handsome-wjc/p/11264509.html