蓝桥杯C++ AB组辅导课 第二讲 二分与前缀和 Acwing
例題
AcWing 789. 數的范圍
給定一個按照升序排列的長度為 n 的整數數組,以及 q 個查詢。
對于每個查詢,返回一個元素 k 的起始位置和終止位置(位置從 0 開始計數)。
如果數組中不存在該元素,則返回 -1 -1。
輸入格式
第一行包含整數 n 和 q,表示數組長度和詢問個數。
第二行包含 n 個整數(均在 1~10000 范圍內),表示完整數組。
接下來 q 行,每行包含一個整數 k,表示一個詢問元素。
輸出格式
共 q 行,每行包含兩個整數,表示所求元素的起始位置和終止位置。
如果數組中不存在該元素,則返回 -1 -1。
數據范圍
1≤n≤100000 1≤q≤10000 1≤k≤10000輸入樣例:
6 3 1 2 2 3 3 4 3 4 5輸出樣例:
3 4 5 5 -1 -1 #include <iostream> using namespace std;const int N = 1e5 + 10;int a[N];int main() {int n, q; cin >> n >> q;for (int i = 1; i <= n && cin >> a[i]; i ++ );while (q -- ){int k; cin >> k;int l = 0, r = n + 1;while (l + 1 != r){int m = l + r >> 1;if (a[m] < k) l = m;else r = m;}if (a[r] != k){cout << -1 << ' ' << -1 << endl;continue;}cout << r - 1 << ' ';l = 0, r = n + 1;while (l + 1 != r){int m = l + r >> 1;if (a[m] <= k) l = m;else r = m;}cout << l - 1 << endl;} }AcWing 790. 數的三次方根
給定一個浮點數 n,求它的三次方根。
輸入格式
共一行,包含一個浮點數 n。
輸出格式
共一行,包含一個浮點數,表示問題的解。
注意,結果保留 6 位小數。
數據范圍
?10000≤n≤10000輸入樣例:
1000.00輸出樣例:
10.000000 #include <iostream> #include <iomanip> using namespace std;const double esp = 1e-8;int main() {double n; cin >> n;double l = -1e4 - 10, r = 1e4 + 10;while (r - l > esp){double m = (l + r) / 2;if (m * m * m >= n) r = m;else l = m;}cout << fixed << setprecision(6) << r; }AcWing 795. 前綴和
輸入一個長度為 n 的整數序列。
接下來再輸入 m 個詢問,每個詢問輸入一對 l,r。
對于每個詢問,輸出原序列中從第 l 個數到第 r 個數的和。
輸入格式
第一行包含兩個整數 n 和 m。
第二行包含 n 個整數,表示整數數列。
接下來 m 行,每行包含兩個整數 l 和 r,表示一個詢問的區間范圍。
輸出格式
共 m 行,每行輸出一個詢問的結果。
數據范圍
1≤l≤r≤n, 1≤n,m≤100000, ?1000≤數列中元素的值≤1000輸入樣例:
5 3 2 1 3 6 4 1 2 1 3 2 4輸出樣例:
3 6 10 #include <iostream> using namespace std;const int N = 1e5 + 10;int n, m; int a[N];int main() {cin >> n >> m;for (int i = 1; i <= n && cin >> a[i]; i ++ ) a[i] += a[i - 1];while (m -- ){int l, r; cin >> l >> r;cout << a[r] - a[l - 1] << endl;} }AcWing 796. 子矩陣的和
輸入一個 n 行 m 列的整數矩陣,再輸入 q 個詢問,每個詢問包含四個整數 x1,y1,x2,y2,表示一個子矩陣的左上角坐標和右下角坐標。
對于每個詢問輸出子矩陣中所有數的和。
輸入格式
第一行包含三個整數 n,m,q。
接下來 n 行,每行包含 m 個整數,表示整數矩陣。
接下來 q 行,每行包含四個整數 x1,y1,x2,y2,表示一組詢問。
輸出格式
共 q 行,每行輸出一個詢問的結果。
數據范圍
1≤n,m≤1000, 1≤q≤200000, 1≤x1≤x2≤n, 1≤y1≤y2≤m, ?1000≤矩陣內元素的值≤1000輸入樣例:
3 4 3 1 7 2 4 3 6 2 8 2 1 2 3 1 1 2 2 2 1 3 4 1 3 3 4輸出樣例:
17 27 21 #include <iostream> using namespace std;const int N = 1010;int n, m, q; int a[N][N];int main() {cin >> n >> m >> q;for (int i = 1; i <= n; i ++ )for (int j = 1; j <= m; j ++ ){cin >> a[i][j];a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + a[i][j];}while (q -- ){int x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;cout << a[x2][y2] - a[x1 - 1][y2] - a[x2][y1 - 1] + a[x1 - 1][y1 - 1] << endl;} }習題
AcWing 730. 機器人跳躍問題
機器人正在玩一個古老的基于 DOS 的游戲。
游戲中有 N+1 座建筑——從 0 到 N 編號,從左到右排列。
編號為 0 的建筑高度為 0 個單位,編號為 i 的建筑高度為 H(i) 個單位。
起初,機器人在編號為 0 的建筑處。
每一步,它跳到下一個(右邊)建筑。
假設機器人在第 k 個建筑,且它現在的能量值是 E,下一步它將跳到第 k+1 個建筑。
如果 H(k+1)>E,那么機器人就失去 H(k+1)?E 的能量值,否則它將得到 E?H(k+1) 的能量值。
游戲目標是到達第 N 個建筑,在這個過程中能量值不能為負數個單位。
現在的問題是機器人至少以多少能量值開始游戲,才可以保證成功完成游戲?
輸入格式
第一行輸入整數 N。
第二行是 N 個空格分隔的整數,H(1),H(2),…,H(N) 代表建筑物的高度。
輸出格式
輸出一個整數,表示所需的最少單位的初始能量值上取整后的結果。
數據范圍
1≤N,H(i)≤105,輸入樣例1:
5 3 4 3 2 4輸出樣例1:
4題意 :
- 初始時e = h[0],依次遍歷數列,e += e - h[i],求最小的h[0](向上取整)使得過程中e永遠大于等于0
思路 :
- 易知,h[0]越大,整個過程中所有的e越大,因此,具有單調性
- 剪枝 :因為h[i]的范圍是[1,1e5][1,1e5][1,1e5],因此根據公式,只要在某一狀態下e達到1e5,之后一定遞增或不變,直接返回true
AcWing 1221. 四平方和
四平方和定理,又稱為拉格朗日定理:
每個正整數都可以表示為至多 4 個正整數的平方和。
如果把 0 包括進去,就正好可以表示為 4 個數的平方和。
比如:
5=02+02+12+22
7=12+12+12+22
對于一個給定的正整數,可能存在多種平方和的表示法。
要求你對 4 個數排序:
0≤a≤b≤c≤d
并對所有的可能表示法按 a,b,c,d 為聯合主鍵升序排列,最后輸出第一個表示法。
輸入格式
輸入一個正整數 N。
輸出格式
輸出4個非負整數,按從小到大排序,中間用空格分開。
數據范圍
0<N<5?106輸入樣例:
5輸出樣例:
0 0 1 2思路 :
- 暴力O(n4)O(n^4)O(n4) 優化為 暴力O(n3)O(n^3)O(n3),仍然超時
- 哈希表法 雖然復雜度為O(n2)O(n^2)O(n2),但常數太大,仍然超時
- 采用二分法,雖然復雜度為O(n2logn)O(n^2logn)O(n2logn),可以通過
- 二分枚舉的時候仍然需要優化;有兩個枚舉優化之處:1.雙重循環時,易知第二重循環c * c + d * d <= n;2.第二個優化不容易發現,而且是題目的先決條件,0≤a≤b≤c≤d0≤a≤b≤c≤d0≤a≤b≤c≤d,因此第二重循環以第一重循環為起始
AcWing 1227. 分巧克力
兒童節那天有 K 位小朋友到小明家做客。
小明拿出了珍藏的巧克力招待小朋友們。
小明一共有 N 塊巧克力,其中第 i 塊是 Hi×Wi 的方格組成的長方形。
為了公平起見,小明需要從這 N 塊巧克力中切出 K 塊巧克力分給小朋友們。
切出的巧克力需要滿足:
形狀是正方形,邊長是整數
大小相同
例如一塊 6×5 的巧克力可以切出 6 塊 2×2 的巧克力或者 2 塊 3×3 的巧克力。
當然小朋友們都希望得到的巧克力盡可能大,你能幫小明計算出最大的邊長是多少么?
輸入格式
第一行包含兩個整數 N 和 K。
以下 N 行每行包含兩個整數 Hi 和 Wi。
輸入保證每位小朋友至少能獲得一塊 1×1 的巧克力。
輸出格式
輸出切出的正方形巧克力最大可能的邊長。
數據范圍
1≤N,K≤105, 1≤Hi,Wi≤105輸入樣例:
2 10 6 5 5 6輸出樣例:
2 #include <iostream> using namespace std;const int N = 1e5 + 10;int n, k; int h[N], w[N];bool check(int len) {int res = 0;for (int i = 1; i <= n; i ++ ){res += (h[i] / len) * (w[i] / len);if (res >= k) return true;}return false; }int main() {cin >> n >> k;for (int i = 1; i <= n && cin >> h[i] >> w[i]; i ++ );int l = 0, r = 1e5 + 1;while (l + 1 != r){int mid = l + r >> 1;if (check(mid)) l = mid;else r = mid;}cout << l; }AcWing 99. 激光炸彈
地圖上有 N 個目標,用整數 Xi,Yi 表示目標在地圖上的位置,每個目標都有一個價值 Wi。
注意:不同目標可能在同一位置。
現在有一種新型的激光炸彈,可以摧毀一個包含 R×R 個位置的正方形內的所有目標。
激光炸彈的投放是通過衛星定位的,但其有一個缺點,就是其爆炸范圍,即那個正方形的邊必須和 x,y 軸平行。
求一顆炸彈最多能炸掉地圖上總價值為多少的目標。
輸入格式
第一行輸入正整數 N 和 R,分別代表地圖上的目標數目和正方形的邊長,數據用空格隔開。
接下來 N 行,每行輸入一組數據,每組數據包括三個整數 Xi,Yi,Wi,分別代表目標的 x 坐標,y 坐標和價值,數據用空格隔開。
輸出格式
輸出一個正整數,代表一顆炸彈最多能炸掉地圖上目標的總價值數目。
數據范圍
0≤R≤109 0<N≤10000, 0≤Xi,Yi≤5000 0≤Wi≤1000輸入樣例:
2 1 0 0 1 1 1 1輸出樣例:
1思路 :
- 由輸入的數據我們可以得到這個地圖的寬高;注意這個地圖的寬高至少是R,否則就無法進入循環了
- R最多是5001,多出來的部分沒有意義
- 枚舉框起來的范圍時,注意我們枚舉右下角
AcWing 1230. K倍區間
給定一個長度為 N 的數列,A1,A2,…AN,如果其中一段連續的子序列 Ai,Ai+1,…Aj 之和是 K 的倍數,我們就稱這個區間 [i,j] 是 K 倍區間。
你能求出數列中總共有多少個 K 倍區間嗎?
輸入格式
第一行包含兩個整數 N 和 K。
以下 N 行每行包含一個整數 Ai。
輸出格式
輸出一個整數,代表 K 倍區間的數目。
數據范圍
1≤N,K≤100000, 1≤Ai≤100000輸入樣例:
5 2 1 2 3 4 5輸出樣例:
6題意 :
- 這里i可以等于j
思路 :
- (sum[r]?sum[l?1])(sum[r] - sum[l - 1])(sum[r]?sum[l?1]) % k == 0,推出sum[r] % k == sum[l - 1] % k
- 因此,一維循環即可。遍歷到第i個元素時,只要答案累加 前面 與它 模的結果相同 的個數即可,同時 維護 模的結果 的序列
- 注意這道題開long long,因為區間數溢出int了
總結
以上是生活随笔為你收集整理的蓝桥杯C++ AB组辅导课 第二讲 二分与前缀和 Acwing的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 王道计算机考研 计算机组成原理 第一章、
- 下一篇: 王道计算机考研 计算机组成原理 第二章、