線段樹學習筆記 - 練習題(2)

文章目錄

  • 1. 前言
  • 2. P3870 [TJOI2009] 開關
  • 3. P2184 貪婪大陸
  • 4. P1438 無聊的數列
  • 5. P1471 方差

1. 前言

線段樹系列文章:

  • 線段樹學習筆記。
  • 線段樹學習筆記 - 練習題(1)。

前一篇做了幾道線段樹的題目,這篇文章就繼續看下線段樹的相關題目,還是一樣,學習視頻:算法講解112【擴展】線段樹專題3-線段樹維護更多類型的信息,題目都是左神視頻上的,思路也可以看這個視頻。


2. P3870 [TJOI2009] 開關

P3870 [TJOI2009] 開關。

題目描述

現有 nnn 盞燈排成一排,從左到右依次編號為:111222,……,nnn。然后依次執行 mmm 項操作。

操作分為兩種:

  1. 指定一個區間 [a,b][a,b][a,b],然后改變編號在這個區間內的燈的狀態(把開著的燈關上,關著的燈打開);
  2. 指定一個區間 [a,b][a,b][a,b],要求你輸出這個區間內有多少盞燈是打開的。

燈在初始時都是關著的。

輸入格式

第一行有兩個整數 nnnmmm,分別表示燈的數目和操作的數目。

接下來有 mmm 行,每行有三個整數,依次為:cccaaabbb。其中 ccc 表示操作的種類。

  • ccc 的值為 000 時,表示是第一種操作。
  • ccc 的值為 111 時,表示是第二種操作。

aaabbb 則分別表示了操作區間的左右邊界。

輸出格式

每當遇到第二種操作時,輸出一行,包含一個整數,表示此時在查詢的區間中打開的燈的數目。

輸入輸出樣例 #1

輸入 #1

4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4

輸出 #1

1
2

說明/提示

數據規模與約定

對于全部的測試點,保證 2≤n≤1052\le n\le 10^52n1051≤m≤1051\le m\le 10^51m1051≤a,b≤n1\le a,b\le n1a,bnc∈{0,1}c\in\{0,1\}c{0,1}

思路:

這道題就是范圍重置和范圍查詢,初始值為 0 表示燈是關上的,1 表示燈打開了,其實就是范圍重置維護累加和,那么如果到了一個范圍能不能在 O(1) 時間內懶更新完這個范圍的累加和呢?答案是可以的,比如這個范圍長度是 n,假設現在 light[i] = m,那么翻轉過后 light[i] = n - m,所以是可以 O(1) 時間懶更新的,下面看下 code。

import java.io.*;public class Main {public static int MAXN = 100001;public static int[] light = new int[MAXN << 2];// 懶更新數組, 如果為 true 就表示這個范圍內的值要翻轉了public static boolean[] reverse = new boolean[MAXN << 2];public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));in.nextToken();int n = (int) in.nval;in.nextToken();int m = (int) in.nval;build(1, n, 1);for (int i = 1, op, jobl, jobr; i <= m; i++) {in.nextToken();op = (int) in.nval;in.nextToken();jobl = (int) in.nval;in.nextToken();jobr = (int) in.nval;if (op == 0) {reverse(jobl, jobr, 1, n, 1);} else {out.println(query(jobl, jobr, 1, n, 1));}}out.flush();out.close();br.close();}private static int query(int jobl, int jobr, int l, int r, int i) {if (jobl <= l && r <= jobr) {return light[i];} else {int ans = 0;int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if (jobl <= mid) {ans += query(jobl, jobr, l, mid, i << 1);}if (jobr > mid) {ans += query(jobl, jobr, mid + 1, r, i << 1 | 1);}return ans;}}private static void reverse(int jobl, int jobr, int l, int r, int i) {if (jobl <= l && r <= jobr) {lazy(i, r - l + 1);} else {int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if (jobl <= mid) {reverse(jobl, jobr, l, mid, i << 1);}if (jobr > mid) {reverse(jobl, jobr, mid + 1, r, i << 1 | 1);}up(i);}}private static void down(int i, int ln, int rn) {if (reverse[i]) {lazy(i << 1, ln);lazy(i << 1 | 1, rn);reverse[i] = false;}}private static void lazy(int i, int n) {light[i] = n - light[i];// 假設子數組是 true, 那么再次翻轉就是 !reverse[i]// 不能直接設置為 falsereverse[i] = !reverse[i];}private static void build(int l, int r, int i) {if (l == r) {light[i] = 0;} else {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);up(i);}reverse[i] = false;}private static void up(int i) {light[i] = light[i << 1] + light[i << 1 | 1];}
}

3. P2184 貪婪大陸

P2184 貪婪大陸。

題目背景

面對螞蟻們的瘋狂進攻,小 FF 的 Tower defence 宣告失敗……人類被螞蟻們逼到了 Greed Island 上的一個海灣。現在,小 FF 的后方是一望無際的大海,前方是變異了的超級螞蟻。小 FF 還有大好前程,他可不想命喪于此, 于是他派遣手下最后一批改造 SCV 布置地雷以阻擋螞蟻們的進攻。

題目描述

小 FF 最后一道防線是一條長度為 nnn 的戰壕,小 FF 擁有無數多種地雷,而 SCV 每次可以在 [L,R][L, R][L,R] 區間埋放同一種不同于之前已經埋放的地雷。由于情況已經十萬火急,小 FF 在某些時候可能會詢問你在 [L′,R′][L',R'][L,R] 區間內有多少種不同的地雷,他希望你能盡快的給予答復。

輸入格式

第一行為兩個整數 nnnmmmnnn 表示防線長度,mmm 表示 SCV 布雷次數及小 FF 詢問的次數總和。

接下來有 mmm 行,每行三個整數 q,l,rq,l,rq,l,r

  • q=1q=1q=1,則表示 SCV 在 [l,r][l, r][l,r] 這段區間布上一種地雷;
  • q=2q=2q=2,則表示小 FF 詢問當前 [l,r][l, r][l,r] 區間總共有多少種地雷。

輸出格式

對于小 FF 的每次詢問,輸出一個答案(單獨一行),表示當前區間地雷總數。

輸入輸出樣例 #1

輸入 #1

5 4
1 1 3
2 2 5
1 2 4
2 3 5

輸出 #1

1
2

說明/提示

數據規模與約定

  • 對于 30%30\%30% 的數據,0≤n0 \le n0nm≤1000m \le 1000m1000
  • 對于 100%100\%100% 的數據,0≤n0 \le n0nm≤105m \le 10^5m105

思路:

這道題就是兩個操作,放地雷和查地雷數,注意這里就不是范圍更新了,比如 [1,4] 區間現在放了地雷 1,[3,6] 區間放了地雷 2,那么最終 [3,4] 區間地雷數就是 2,也就是說地雷數是疊加的,而不是被覆蓋的關系。

那么能不能每一次都區間 + 1 然后維護最大值呢,這樣是可以表示這個區間的地雷數,但是最后查詢的時候還是沒辦法查出來總的地雷數。還是上面的例子,比如 [1,4] 區間現在放了地雷 1,[3,6] 區間放了地雷 2,[2,2] 區間放了地雷 3,最終結果如下。
在這里插入圖片描述
然后我們要查詢 [1,6] 范圍的地雷數,結果是 3,但是如果維護的最大值,那最大值就是 2,也就是 [2,4] 這個區間的最大值是 2,但是根據這個最大值是沒辦法算出總地雷數的,所以得另外想個辦法,既然維護整個區間是不行的,那么能不能維護左右邊界來求地雷總數呢,我們可以用 left 和 right 兩個數組來維護地雷的左右邊界,left[i] 表示這個范圍的地雷左邊界總數,right[i] 表示這個范圍的地雷右邊界總數,更新的時候不用范圍更新了,因為就算是范圍更新也是 [l,l] 更新和 [r,r] 更新,也就是單點更新了,所以直接深入到葉子節點去更新,然后再維護累加和,整體時間復雜度是 O(n?log2n)O(n * log_{2}{n})O(n?log2?n)

那么查詢要如何查詢呢,來看下下面的圖。

在這里插入圖片描述

上面圖一共埋了 4 個地雷,范圍是從 1-8,比如我們要求 [3,7] 這個范圍內一共有多少地雷,首先求出來 [1,r] 這個范圍包含了多少個地雷的左邊界,然后再求出 [1,2] 包含了多少地雷的右邊界,一相減就求出結果了,總結來說就是加入 [l,r] 范圍先求出 [1,r] 范圍有多少地雷的左邊界,然后求出 [1,l - 1] 范圍有多少地雷的右邊界,再相減。

在這里插入圖片描述

這樣求出來的結果是 4,那么為什么可以這么求,首先要明確什么地雷會落在 [l,r] 范圍。

在這里插入圖片描述

可以看到,這兩種可以就可以概括了,就是下面兩種:

  • 左邊界 < l,右邊界 >= l
  • l < 左邊界 < r

所以可以看到,匯總以下,最終要落在 [l,r] 范圍的地雷左邊界肯定是要 <= r 的,于是第一步就是求出 [1,r] 這個范圍的有多少個地雷的左邊界,然后右邊界肯定是不能小于 l 的,如果小于 l 就落不到這個區間了,所以求出來右邊界 <= l - 1 的地雷數,然后相減就行了,下面看下 code。


import java.io.*;public class Main {public static int MAXN = 100001;public static int[] left = new int[MAXN << 2];public static int[] right = new int[MAXN << 2];public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));in.nextToken();int n = (int) in.nval;in.nextToken();int m = (int) in.nval;build(1, n, 1);for (int i = 1; i <= m; i++) {in.nextToken();int op = (int) in.nval;in.nextToken();int jobl = (int) in.nval;in.nextToken();int jobr = (int) in.nval;if (op == 1) {add(0, jobl, 1, n, 1);add(1, jobr, 1, n, 1);} else {// [1, r] 的左邊界 - [1, l-1] 的右邊界地雷數int cl = query(0, 1, jobr, 1, n, 1);int cr = jobl == 1 ? 0 : query(1, 1, jobl - 1, 1, n, 1);out.println(cl - cr);}}out.flush();out.close();br.close();}public static int query(int type, int jobl, int jobr, int l, int r, int i) {if (jobl <= l && r <= jobr) {return type == 0 ? left[i] : right[i];}int res = 0;int mid = l + ((r - l) >> 1);if (jobl <= mid) {res += query(type, jobl, jobr, l, mid, i << 1);}if (jobr > mid) {res += query(type, jobl, jobr, mid + 1, r, i << 1 | 1);}return res;}public static void add(int type, int jobi, int l, int r, int i) {// 更新直接到葉子節點更新,不需要懶更新了,數據量不大if (l == r) {if (type == 0) {left[i]++;} else {right[i]++;}} else {int mid = l + ((r - l) >> 1);if (jobi <= mid) {add(type, jobi, l, mid, i << 1);}if (jobi > mid) {add(type, jobi, mid + 1, r, i << 1 | 1);}up(i);}}private static void up(int i) {left[i] = left[i << 1] + left[i << 1 | 1];right[i] = right[i << 1] + right[i << 1 | 1];}private static void build(int l, int r, int i) {if (l == r) {left[i] = right[i] = 0;} else {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);}}}

4. P1438 無聊的數列

P1438 無聊的數列

題目背景

無聊的 YYB 總喜歡搞出一些正常人無法搞出的東西。有一天,無聊的 YYB 想出了一道無聊的題:無聊的數列。。。

題目描述

維護一個數列 aia_iai?,支持兩種操作:

  • 1 l r K D:給出一個長度等于 r?l+1r-l+1r?l+1 的等差數列,首項為 KKK,公差為 DDD,并將它對應加到 [l,r][l,r][l,r] 范圍中的每一個數上。即:令 al=al+K,al+1=al+1+K+D…ar=ar+K+(r?l)×Da_l=a_l+K,a_{l+1}=a_{l+1}+K+D\ldots a_r=a_r+K+(r-l) \times Dal?=al?+K,al+1?=al+1?+K+Dar?=ar?+K+(r?l)×D

  • 2 p:詢問序列的第 ppp 個數的值 apa_pap?

輸入格式

第一行兩個整數數 n,mn,mn,m 表示數列長度和操作個數。

第二行 nnn 個整數,第 iii 個數表示 aia_iai?

接下來的 mmm 行,每行先輸入一個整數 optoptopt

opt=1opt=1opt=1 則再輸入四個整數 lrKDl\ r\ K\ Dl?r?K?D

opt=2opt=2opt=2 則再輸入一個整數 ppp

輸出格式

對于每個詢問,一行一個整數表示答案。

輸入輸出樣例 #1

輸入 #1

5 2
1 2 3 4 5
1 2 4 1 2
2 3

輸出 #1

6

說明/提示

數據規模與約定

對于 100%100\%100% 數據,0≤n,m≤105,?200≤ai,K,D≤200,1≤l≤r≤n,1≤p≤n0\le n,m \le 10^5,-200\le a_i,K,D\le 200, 1 \leq l \leq r \leq n, 1 \leq p \leq n0n,m105,?200ai?,K,D200,1lrn,1pn

思路:

這個就是要加一個等差數列,而且比較特殊的一點就是這里第 2 個操作不是范圍查詢,只是單點查詢,因此這里可以對差分數組構造線段樹,那么對于第一個操作,首項為 k,公差為 d 的等差數列,假設 k = 2,d = 3,假設 l = 2,r = 5,那么添加的等差數列就是 2,2 + 3,2 + 3 * 2, 2 + 33,2 + 34。

對于線段樹維護差分數組的范圍增加還是比較容易的,首先就是在 [2,2] 的位置 + 2,然后在 [3,5] 范圍 + 3,最后別忘了在 6 位置減去總和,也就是減去 2 + (3 * 4),這是差分數組的性質決定的,比如要在原數組 [l,r] 范圍 + v,那么對于差分數組的修改就是 d[l] + v,d[r + 1] - v,這樣求前綴和的時候求出來原數組的 [l,r] 范圍就都是 v 了,對于線段數也是,由于差分數組這個范圍增加到 r 這個區間一共加了 2 + (3 * 4),因此 r + 1 位置減去 2 + (3 * 4) 抵消影響,這樣線段樹 query 求 [1,p] 的范圍總和就是下標 p 的原數組值了。


import java.io.*;public class Main {public static int MAXN = 100001;public static long[] diff = new long[MAXN];public static long[] sum = new long[MAXN << 2];public static long[] add = new long[MAXN << 2];public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));in.nextToken();int n = (int) in.nval;in.nextToken();int m = (int) in.nval;int pre = 0, cur = 0;for (int i = 1; i <= n; i++) {in.nextToken();cur = (int) in.nval;diff[i] = cur - pre;pre = cur;}build(1, n, 1);for (int i = 1; i <= m; i++) {in.nextToken();int op = (int) in.nval;if (op == 1) {in.nextToken();int jobl = (int) in.nval;in.nextToken();int jobr = (int) in.nval;in.nextToken();long k = (long) in.nval;in.nextToken();long d = (long) in.nval;long e = k + d * (jobr - jobl);add(jobl, jobl, k, 1, n, 1);if (jobl < jobr) {add(jobl + 1, jobr, d, 1, n, 1);}if (jobr + 1 <= n) {add(jobr + 1, jobr + 1, -e, 1, n, 1);}} else {in.nextToken();int p = (int) in.nval;out.println(query(1, p, 1, n, 1));}}out.flush();out.close();br.close();}private static long query(int jobl, int jobr, int l, int r, int i) {if (jobl <= l && r <= jobr) {return sum[i];}long ans = 0;int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if (jobl <= mid) {ans += query(jobl, jobr, l, mid, i << 1);}if (jobr > mid) {ans += query(jobl, jobr, mid + 1, r, i << 1 | 1);}return ans;}private static void build(int l, int r, int i) {if (l == r) {sum[i] = diff[l];} else {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);up(i);}add[i] = 0;}private static void up(int i) {sum[i] = sum[i << 1] + sum[i << 1 | 1];}public static void add(int jobl, int jobr, long jobv, int l, int r, int i) {if (jobl <= l && r <= jobr) {lazy(i, jobv, r - l + 1);} else {int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if (jobl <= mid) {add(jobl, jobr, jobv, l, mid, i << 1);}if (jobr > mid) {add(jobl, jobr, jobv, mid + 1, r, i << 1 | 1);}up(i);}}private static void down(int i, int ln, int rn) {if (add[i] != 0) {lazy(i << 1, add[i], ln);lazy(i << 1 | 1, add[i], rn);add[i] = 0;}}private static void lazy(int i, long v, int cnt) {sum[i] += v * cnt;add[i] += v;}}

5. P1471 方差

P1471 方差。

題目背景

滾粗了的 HansBug 在收拾舊數學書,然而他發現了什么奇妙的東西。

題目描述

蒟蒻 HansBug 在一本數學書里面發現了一個神奇的數列,包含 NNN 個實數。他想算算這個數列的平均數和方差。

輸入格式

第一行包含兩個正整數 N,MN,MN,M,分別表示數列中實數的個數和操作的個數。

第二行包含 NNN 個實數,其中第 iii 個實數表示數列的第 iii 項。

接下來 MMM 行,每行為一條操作,格式為以下三種之一:

操作 1111 x y k ,表示將第 xxx 到第 yyy 項每項加上 kkkkkk 為一實數。
操作 2222 x y ,表示求出第 xxx 到第 yyy 項這一子數列的平均數。
操作 3333 x y ,表示求出第 xxx 到第 yyy 項這一子數列的方差。

輸出格式

輸出包含若干行,每行為一個實數,即依次為每一次操作 222 或操作 333 所得的結果(所有結果四舍五入保留 444 位小數)。

輸入輸出樣例 #1

輸入 #1

5 5
1 5 4 2 3
2 1 4
3 1 5
1 1 1 1
1 2 2 -1
3 1 5

輸出 #1

3.0000
2.0000
0.8000

說明/提示

關于方差:對于一個有 nnn 項的數列 AAA,其方差 s2s^2s2 定義如下:
s2=1n∑i=1n(Ai?A ̄)2s^2=\frac{1}{n}\sum\limits_{i=1}^n\left(A_i-\overline A\right)^2s2=n1?i=1n?(Ai??A)2
其中 A ̄\overline AA 表示數列 AAA 的平均數,AiA_iAi? 表示數列 AAA 的第 iii 項。

數據規模:

數據點NNNMMM備注
1~31\sim313N≤8N\le 8N8M≤15M\le 15M15-
4~74\sim747N≤105N\le 10^5N105M≤105M\le 10^5M105不包含操作 333
8~108\sim10810N≤105N\le 10^5N105M≤105M\le 10^5M105-

思路:

首先為了維護平均數,我們可以維護一個累加和信息,求平均數的時候就用累加和 / 區間長度就可以了,那么如何表示方差呢,下面來推導下。

  • ∑i=1n(Ai?Aˉ)2=(A12+Aˉ2?2?A1?Aˉ)+(A22+Aˉ2?2?A2?Aˉ)+...+(An2+Aˉ2?2?An?Aˉ)=(A12+A22+...+An2)?2?Aˉ?(A1+A2+...+An)+n?Aˉ2=∑i=1nAi2?n?Aˉ2{\textstyle \sum_{i = 1}^{n}} (A_{i} - \bar{A})^2 = (A_{1}^2 + \bar{A}^2 - 2 * A_{1} * \bar{A}) + (A_{2}^2 + \bar{A}^2 - 2 * A_{2} * \bar{A}) + ... + (A_{n}^2 + \bar{A}^2 - 2 * A_{n} * \bar{A}) = (A_{1}^2 + A_{2}^2 + ... + A_{n}^2) - 2 * \bar{A} * (A_{1} + A_{2} + ... + A_{n}) + n * \bar{A}^2 = {\textstyle \sum_{i = 1}^{n}} A_{i}^2 - n * \bar{A}^2i=1n?(Ai??Aˉ)2=(A12?+Aˉ2?2?A1??Aˉ)+(A22?+Aˉ2?2?A2??Aˉ)+...+(An2?+Aˉ2?2?An??Aˉ)=(A12?+A22?+...+An2?)?2?Aˉ?(A1?+A2?+...+An?)+n?Aˉ2=i=1n?Ai2??n?Aˉ2
  • ∑i=1n(Ai?Aˉ)2n=∑i=1nAi2n?Aˉ2\frac{{\textstyle \sum_{i = 1}^{n}}(A_{i} - \bar{A})^2}{n} = \frac{{\textstyle \sum_{i = 1}^{n}} A_{i}^2}{n} - \bar{A}^2ni=1n?(Ai??Aˉ)2?=ni=1n?Ai2???Aˉ2

所以這里我們用兩個數組,一個維護累加和,求平均數就用 (sum1 / size) * (sum1 / size),然后再維護一個平方累加和,求第一部分就直接用 sum2 / size,最終結果就是 sum2size?sum12size2\frac{sum2}{size} - \frac{sum1 ^ 2}{size^2}sizesum2??size2sum12?

那么要維護平方累加和,能不能在 O(1) 時間內懶更新完成呢,也是沒問題的,如果沒有累加和數組那肯定不能 O(1) 懶更新完,但是有了累加和,就可以化簡下了,假設現在平方累加和是 sum2[i],比如是 [l,r] 區間的累加和,可以寫成:(A12+A22+...+An2)(A_{1}^2 + A_{2}^2 + ... + A_{n}^2)(A12?+A22?+...+An2?),那么現在這個范圍的每一個數字都加上 k,最終平方累加和變成了:

  • ((A1+k)2+(A2+k)2+...+(An+k)2)((A_{1} + k)^2 + (A_{2} + k)^2 + ... + (A_{n} + k)^2)((A1?+k)2+(A2?+k)2+...+(An?+k)2)

再化簡下變成了:

  • (A12+A22+...+An2)+2?k?(A1+A2+...+Ak)+n?k2(A_{1}^2 + A_{2}^2 + ... + A_{n}^2) + 2 * k * (A_{1} + A_{2} + ... + A_{k}) +n * k ^2(A12?+A22?+...+An2?)+2?k?(A1?+A2?+...+Ak?)+n?k2

那前面的 (A12+A22+...+An2)(A_{1}^2 + A_{2}^2 + ... + A_{n}^2)(A12?+A22?+...+An2?) 就是原來的 sum2[i],然后 2?k?(A1+A2+...+Ak)2 * k * (A_{1} + A_{2} + ... + A_{k})2?k?(A1?+A2?+...+Ak?) 就是 2 * k * sum[i],sum[i] 就是區間累加和,然后最后的 n?k2n * k^2n?k2 也可以 O(1) 時間完成,所以整體都可以在 O(1) 時間內完成,不過要注意一下,由于更新 sum2 需要依賴 sum1,所以需要先更新 sum2 再更新 sum1,然后其他的就跟之前的差不多了,下面看 code。


import java.io.*;
import java.util.StringTokenizer;public class Main {public static int MAXN = 100001;public static double[] arr = new double[MAXN];public static double[] sum1 = new double[MAXN << 2];public static double[] sum2 = new double[MAXN << 2];public static double[] add = new double[MAXN << 2];public static void main(String[] args) {Kattio kattio = new Kattio();int n = kattio.nextInt();int m = kattio.nextInt();for (int i = 1; i <= n; i++) {arr[i] = kattio.nextDouble();}build(1, n, 1);double jobv = 0.0;for (int i = 1, op, jobl, jobr; i <= m; i++) {op = kattio.nextInt();if (op == 1) {jobl = kattio.nextInt();jobr = kattio.nextInt();jobv = kattio.nextDouble();add(jobl, jobr, jobv, 1, n, 1);} else if (op == 2) {jobl = kattio.nextInt();jobr = kattio.nextInt();double res = query(sum1, jobl, jobr, 1, n, 1);kattio.println(String.format("%.4f", res / (jobr - jobl + 1)));} else if (op == 3) {jobl = kattio.nextInt();jobr = kattio.nextInt();double r1 = query(sum1, jobl, jobr, 1, n, 1);double r2 = query(sum2, jobl, jobr, 1, n, 1);int c = jobr - jobl + 1;kattio.println(String.format("%.4f", r2 / c - (r1 / c) * (r1 / c)));}}kattio.flush();kattio.close();}private static double query(double[] sum, int jobl, int jobr, int l, int r, int i) {if (jobl <= l && r <= jobr) {return sum[i];}int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);double res = 0;if (jobl <= mid) {res += query(sum, jobl, jobr, l, mid, i << 1);}if (jobr > mid) {res += query(sum, jobl, jobr, mid + 1, r, i << 1 | 1);}return res;}private static void add(int jobl, int jobr, double jobv, int l, int r, int i) {if (jobl <= l && r <= jobr) {lazy(i, jobv, r - l + 1);} else {int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if (jobl <= mid) {add(jobl, jobr, jobv, l, mid, i << 1);}if (jobr > mid) {add(jobl, jobr, jobv, mid + 1, r, i << 1 | 1);}up(i);}}private static void down(int i, int ln, int rn) {if (add[i] != 0) {lazy(i << 1, add[i], ln);lazy(i << 1 | 1, add[i], rn);add[i] = 0;}}private static void lazy(int i, double v, int cnt) {sum2[i] += 2 * sum1[i] * v + v * v * cnt;sum1[i] += cnt * v;add[i] += v;}private static void build(int l, int r, int i) {if (l == r) {sum1[i] = arr[l];sum2[i] = arr[l] * arr[l];} else {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);up(i);}add[i] = 0;}private static void up(int i) {sum1[i] = sum1[i << 1] + sum1[i << 1 | 1];sum2[i] = sum2[i << 1] + sum2[i << 1 | 1];}public static class Kattio extends PrintWriter {private BufferedReader r;private StringTokenizer st;public Kattio() {this(System.in, System.out);}public Kattio(InputStream i, OutputStream o) {super(o);r = new BufferedReader(new InputStreamReader(i));}public Kattio(String intput, String output) throws IOException {super(output);r = new BufferedReader(new FileReader(intput));}public String next() {try {while (st == null || !st.hasMoreTokens())st = new StringTokenizer(r.readLine());return st.nextToken();} catch (Exception e) {}return null;}public int nextInt() {return Integer.parseInt(next());}public double nextDouble() {return Double.parseDouble(next());}public long nextLong() {return Long.parseLong(next());}}}

不過這個 code 會超過空間限制。
在這里插入圖片描述
視頻里面給了 C++ 版本,用這個版本的可以過,所以直接用視頻里面的 C++ 代碼就行,但是上面的 java 邏輯是對的,照著翻譯成 C++ 也沒問題。





如有錯誤,歡迎指出!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/90198.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/90198.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/90198.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue狀態管理:Pinia 與 Vuex 的使用方法與對比【文章附有完整案例】

最近在接手vue項目的需求&#xff0c;因為之前一直在做react的需求&#xff0c;日常的vue練習也少了很多&#xff0c;導致現在接手vue項目&#xff0c;很多關于vue的知識點基本上忘得干干凈凈了。但是好在有基礎&#xff0c;重新學也會很快掌握。分享這個過程中的一些復習內容。…

OpenMed 項目深度分析:推動醫療 NLP 領域的開源革命

摘要 醫療人工智能(AI)領域因高質量數據和模型的獲取受限而發展緩慢。OpenMed 項目通過開源超過380個醫療命名實體識別(NER)模型,顯著降低了研究與應用門檻。本文從項目背景、技術優勢、應用場景、實施挑戰及未來展望五個方面,系統分析 OpenMed 的核心價值與潛力,揭示其…

大模型開發

什么是Ai&#xff1f;AI的全拼是(Artificial Intelligence)人工智能&#xff0c;使機器能夠像人類一樣思考、學習和解決問題的技術。在AI的應用情況下我們更多的是學習自然語言處理。在自然語言處理(Natural Language Processing&#xff0c;NLP)中&#xff0c;有一項關鍵技術叫…

【正常配置了beast擴展,phpinfo信息也顯示了,但是就是不運行】

正常配置了beast擴展&#xff0c;phpinfo信息也顯示了&#xff0c;但是就是不運行場景原因解決排查過程擴展場景 項目中使用到了beast進行源碼保護&#xff0c;指定類存在&#xff0c;但是報錯信息提示類找不到&#xff0c;beast擴展添加到了正在運行的php版本下的ext文件夾下…

CRMEB 單商戶PRO多商戶通用去版權教程

CRMEB去版權教程&#xff0c;此教程可根據具體版本進行調整&#xff0c;基本適用次方法。 后端版權修改 修改后端管理底部版權及門店后端管理底部版權。 文件位置 \view\admin\src\components\copyright\index.vue 文件位置 \view\admin\src\router\routes.js 文件位置 \vi…

舊物回收小程序系統開發:重塑舊物回收產業新生態

在傳統觀念中&#xff0c;舊物回收往往給人一種臟亂差、效率低下的印象&#xff0c;回收過程繁瑣&#xff0c;回收渠道有限&#xff0c;導致許多可回收物被浪費。然而&#xff0c;隨著信息技術的飛速發展&#xff0c;舊物回收小程序系統的開發正為這一古老行業帶來前所未有的變…

SSE和WebSocket區別到底是什么

文章目錄SSE 與 WebSocket&#xff1a;深入剖析兩者核心差異核心差異&#xff1a;單向 vs. 雙向通信技術細節對比協議與連接數據格式錯誤處理與可靠性適用場景&#xff1a;何時選擇 SSE&#xff0c;何時選擇 WebSocket&#xff1f;總結SSE 與 WebSocket&#xff1a;深入剖析兩者…

西安電子科技大學金融學431考研經歷分享

考研數學是區分度最大的科目之一&#xff0c;如何高效備考&#xff1f;本文為你推薦多位名師和經典書籍&#xff0c;助你在每個階段都能穩步提升&#xff0c;最終沖刺成功。一、考研數學備考策略教師推薦① 高等數學&#xff1a;② 線性代數&#xff1a;③ 概率論與數理統計&am…

laravel RedisException: Connection refused優雅草PMS項目管理系統報錯解決-以及Redis 詳細指南-優雅草卓伊凡

laravel RedisException: Connection refused優雅草PMS項目管理系統報錯解決-以及Redis 詳細指南-優雅草卓伊凡今天來開始更新pms系統&#xff0c;因為我們ppt上面要做&#xff0c;才發現原來打不開&#xff0c;此前主要是事情太多&#xff0c;我們一直有很多東西擱置解決 Lara…

拉力覆冰在線監測裝置:電力線路安全運行的數字化守衛者

在極端天氣頻發的背景下&#xff0c;輸電線路覆冰災害已成為威脅電網穩定運行的關鍵因素。拉力覆冰在線監測裝置通過數字化技術構建起全天候監測體系&#xff0c;為電力運維提供精準數據支撐。本文從技術實現與實際應用價值角度&#xff0c;解析該裝置的核心功能與行業意義。核…

AI面試如何提升物流行業招聘效率?實戰案例解析

每年秋招季&#xff0c;物流行業都會迎來海量應屆生簡歷涌入。面對業務快速擴張與人才篩選壓力&#xff0c;傳統線下面試流程長、標準模糊、成本高昂等問題愈發凸顯。本文通過兩大物流頭部企業的實戰案例&#xff0c;解析AI面試如何破解招聘困局&#xff0c;實現效率與質量的雙…

【機器學習】組合優化問題combination-optimization概述

博主簡介&#xff1a;努力學習的22級計算機科學與技術本科生一枚&#x1f338;博主主頁&#xff1a; Yaoyao2024往期回顧&#xff1a;【二分圖算法】手把手教你學會&#xff1a;染色法&#xff08;判斷二分圖&#xff09;、匈牙利算法&#xff08;二分圖的最大匹配&#xff09;…

Linux網絡編程-osi、udp

網絡&#xff1a;不同主機&#xff0c;進程間通信達到不同主機之間的困難&#xff1a;解決主機之間的硬件層面的互聯互通解決主機之間的軟件層面的互聯互通廣域網&#xff1a;進行大范圍網絡數據交換IP地址&#xff1a;區分不同主機 唯一的&#xff08;軟件地址&#xff09;MAC…

刪除 XML 格式中雙引號內的空格

要使用 Shell 命令刪除 XML 格式中雙引號內的空格&#xff08;僅處理屬性值中的空格&#xff0c;保留標簽外的空格&#xff09;&#xff0c;可以使用以下 sed 命令&#xff1a; sed -i :loop; s/\("[^"]*\) \([^"]*"\)/\1\2/g; t loop filename.xml命令詳解…

電腦聲音修復?【圖文詳解】電腦沒有聲音?聲音異常

一、問題背景 在使用電腦的過程中&#xff0c;聲音異常是很常見的問題。比如明明打開了音頻文件&#xff0c;卻聽不到任何聲音&#xff1b;或者聲音忽大忽小、伴有雜音&#xff1b;或者更新了聲卡驅動后&#xff0c;電腦播放不了聲音了&#xff1b;還有可能是插入耳機后&#x…

【文獻筆記】ARS: Automatic Routing Solver with Large Language Models

ARS: Automatic Routing Solver with Large Language Models https://github.com/Ahalikai/ARS-Routbench/ ARS&#xff1a;基于大語言模型的自動路由求解器 1. 概述 1.1. 研究背景 車輛路徑問題&#xff08;VRP&#xff09;是一類經典的組合優化問題&#xff0c;廣泛應用于…

RK3568筆記九十:基于web顯示RTSP流

若該文為原創文章,轉載請注明原文出處。 在網上看到個方案,使用web顯示RTSP視頻流,思路是前端傳入RTSP地址,cgi通過FFMPEG接收RTSP流并保存成avi文件,在通過ffmpeg 命令把avi文件保存成mp4文件,前端在播放mp4文件。此方案需要先保存文件,在轉換文件,無法實時播放。 所以…

2025年Flutter開發主流技術棧

2025年Flutter開發主流技術棧 Flutter作為一種高效、跨平臺的移動應用開發框架&#xff0c;近年來在開發者社區中越來越受歡迎。以下是2025年Flutter開發的主流技術棧&#xff0c;涵蓋了從核心框架到開發工具、狀態管理、數據存儲等多個方面。 1. 核心框架 Flutter&#xff1a;…

Qt 常用控件 - 1

控件概述 編程講究的是 --- 站在巨人的肩膀上 --- 不是編寫一個圖形化界面上的內容 --- Qt 已經提供了很多控件了&#xff01;&#xff01;&#xff01;提高圖形化界面的開發效率&#xff01;&#xff01;&#xff01;重點變成我們怎么使用這些已有的控件&#xff01; Widge…

springdoc-openapi-ui的使用教程

<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>1.6.14</version> </dependency>springdoc-openapi-ui 是一個用于生成 OpenAPI 文檔的庫&#xff0c;它與 Swagger 的關…