區間加,區間查詢,顯然的線段樹 & 分塊
說實話第一眼看到這個題的時候我是很懵的:
線段樹每個區間要維護什麼呢?
我們定義\(sum = \sum\limits_^n a_i = a_1 + a_2 + \ldots + a_n\)
\(\qquad \quad pow = \sum\limits_^n a_i^2 = a_1^2 + a_2^2 + \ldots + a_n^2\)
還要知道平均數的公式 \(\overline = \cfrac\)
先把方差的計算公式展開一下:
\[\begin
\large
s^2 &= \cfrac \sum_^n\left(a_i - \overline\right)^2\\
&= \cfrac - \overline \right)^2 + \left(a_ - \overline \right)^2 + \ldots + \left(a_ - \overline \right)^2} \\
&= \cfrac \times \left(a_1 + a_2 + \ldots + a_n \right) + n \times \overline^2}\\
&= \cfrac \times sum + n \times \overline^2}\\
&= \cfrac - 2 \overline^2 + \overline^2\\
&= \cfrac - \cfrac
\end\]
而上面的式子可以由 \(sum\) 和 \(pow\) 求得(\(n\) 為區間長度),所以我們只要維護每個區間的區間和以及平方和即可。(●'◡'●)
然後我們再來求一下區間修改的式子。
若是給 \(a_1\) 到 \(a_n\) 這段區間加上有個數 \(k\),區間和比較簡單就不列式子了,區間平方和就為:
\[\begin
ans &= (a_1 + k)^2 + (a_ + k)^2 + \ldots + (a_ + k)^2 \\
&= a_1^2 + a_^2 + \ldots + a_n^2 + 2k(a_1 + a_2 + \ldots + a_n) + n * k^2\\
&= pow + 2k \cdot sum + n \cdot k^2\\
&= pow + k \cdot (2 \times sum + n \times k) \quad \text
\end\]
然後我們就得到了這道題所要用的所有公式,只需將 \(1 \sim n\) 這個區間推廣到題目給的區間 \(l \sim r\) 即可。
於是我們的pushdown
(下傳懶標記)和add
(區間加)函式就很好寫了:
inline void add(int l, int r, double k, int node)
if(t[node].lazy) pushdown(node);
int mid = t[node].l + t[node].r >> 1;
if(l <= mid) add(l, r, k, node << 1);
if(mid < r) add(l, r, k, node << 1 | 1);
update(node);
}inline void pushdown(int node)
其中每個節點維護的sum
和pow
與上文中意義一致。
for(int i = 1; i <= m; i++)
double **erage = ask_sum(x, y, 1) / (y - x + 1); //這裡的 **erage 表示區間的平均值,用變數記錄一下減少重複運算;
if(check == 2)
if(check == 3)
}
由於比較長就在這不放全部**了,剩下的部分都是線段樹的基本操作。
還有唯一一點要注意的就是題目中給的數列為實數,不一定是整數,存數列的陣列一定要開double
啊!!!
至於文章開頭提到的分塊,太麻煩不想寫了。
洛谷 P1471 方差
題目背景 滾粗了的hansbug在收拾舊數學書,然而他發現了什麼奇妙的東西。題目描述 蒟蒻hansbug在一本數學書裡面發現了乙個神奇的數列,包含n個實數。他想算算這個數列的平均數和方差。輸入輸出格式 輸入格式 第一行包含兩個正整數n m,分別表示數列中實數的個數和操作的個數。第二行包含n個實數,其...
洛谷P1471 方差
題目描述 蒟蒻hansbug在一本數學書裡面發現了乙個神奇的數列,包含 n 個實數。他想算算這個數列的平均數和方差。輸入輸出格式 輸入格式 第一行包含兩個正整數 n m 分別表示數列中實數的個數和操作的個數。第二行包含 n 個實數,其中第 i 個實數表示數列的第 i 項。接下來m行,每行為一條操作,...
洛谷 P1471 方差
蒟蒻hansbug在一本數學書裡面發現了乙個神奇的數列,包含n個實數。他想算算這個數列的平均數和方差。那麼只要維護區間平方和,就可以求方差了。區間平方和,恩,push down稍微改一下即可。注意精度問題。include define n int 1e6 define ll long long us...