Leetcode 327. 區間和的個數 (字首和 + 離散化 + 樹狀陣列)
Leetcode 327. 區間和的個數 (字首和 + 離散化 + 樹狀陣列)
題目
題意
有多少個連續的子陣列,其和在 [ l o w e r , u p p e r ] [lower, upper] [lower,upper]之間
題解
可以想到的做法:用字首和在 O ( 1 ) O(1) O(1)查詢 [ i , j ] [i, j] [i,j]的和,列舉所有的二元組 [ i , j ] [i, j] [i,j], 滿足條件就加上。
可以優化為: P r e Pre Pre為字首和陣列, 從小到大列舉 j j j, 由於 lower ≤ P r e [ j ] − P r e [ i − 1 ] ≤ upper \textit{lower} \leq Pre[j] - Pre[i-1] \leq \textit{upper} lower≤Pre[j]−Pre[i−1]≤upper ,可以得到 P [ i − 1 ] P[i-1] P[i−1] 滿足 P r e [ j ] − upper ≤ P r e [ i − 1 ] ≤ P r e [ j ] − lower Pre[j] - \textit{upper} \leq Pre[i-1] \leq Pre[j] - \textit{lower} Pre[j]−upper≤Pre[i−1]≤Pre[j]−lower ,通過列舉 j j j,可以將 [ P r e [ j ] − upper , P r e [ j ] − lower ] [Pre[j] - \textit{upper}, Pre[j] - \textit{lower}] [Pre[j]−upper,Pre[j]−lower] 看做 [ L , R ] [L, R] [L,R], 之後查詢所有 [ L , R ] [L, R] [L,R]內的個數即為答案。
- 字首和
使用字首和算出子陣列 [ i , j ] [i, j] [i,j]的和 P r e [ j ] − P r e [ i ] Pre[j]-Pre[i] Pre[j]−Pre[i]。
- 離散化
由於資料範圍較大,因此可以通過離散化降低資料。我們可以將 P r e [ j ] − upper , P r e [ j ] − lower , P r e [ j ] Pre[j] - \textit{upper}, Pre[j] - \textit{lower}, Pre[j] Pre[j]−upper,Pre[j]−lower,Pre[j] 一起排序後進行離散化。
- 樹狀陣列 / 線段樹 / 平衡樹
這些資料結構都滿足在 O ( l o g n ) O(logn) O(logn) 的時間複雜度查詢 [ L , R ] [L, R] [L,R]內的和。
程式碼
#define ll long long
class Solution {
public:
vector<int> tree;
int n;
int lowbits(int x){
return x & (-x);
}
void update(int x){
while(x <= n){
tree[x] += 1;
x += lowbits(x);
}
}
int query(int x){
int res = 0;
while(x){
res += tree[x];
x -= lowbits(x);
}
return res;
}
int countRangeSum(vector<int>& nums, int lower, int upper) {
ll sums = 0;
vector<ll> preSum = {0};
for(int x : nums){
sums += x;
preSum.emplace_back(sums);
}
set<ll> st;
for(auto x : preSum){
st.insert(x - lower);
st.insert(x);
st.insert(x - upper);
}
// 離散化
unordered_map<ll, int> p;
int c = 0;
for(auto x : st) p[x] = c++;
int res = 0;
n = p.size();
tree = vector<int> (n+5, 0);
// cout << n << endl;
for(auto x : preSum){
int left = p[x-upper], right = p[x-lower];
res += query(right+1) - query(left);
// cout << x << " " << right << " " << query(right+1) << " " << left << " " << query(left) << endl;
update(p[x]+1);
}
return res;
}
};
相關文章
- 【Leetcode每日一題】327. 區間和的個數(線段樹/樹狀陣列)LeetCode每日一題陣列
- [leetCode]327. 區間和的個數LeetCode
- LeetCode 493. 翻轉對(歸併排序 || 離散化+樹狀陣列)LeetCode排序陣列
- 求區間不同數的個數【樹狀陣列求解】陣列
- 關於區間操作查詢(字首和與差分)+樹狀陣列基礎陣列
- 327. 區間和的個數 (歸併排序)排序
- HDU 5862 Counting Intersections(樹狀陣列+掃描線+離散化)陣列
- 樹狀陣列的區間查詢與區間修改陣列
- 樹狀陣列模板題 & (樹狀陣列 1:單點修改,區間查詢)陣列
- 二維字首和與差分、離散化技巧
- 樹狀陣列和逆序對陣列
- LeetCode 560. 和為K的子陣列(字首和+雜湊+問題轉化)LeetCode陣列
- 1588 所有奇數長度子陣列的和(字首和)陣列
- POJ 3468 【區間修改+區間查詢 樹狀陣列 | 線段樹 | 分塊】陣列
- <二分查詢+雙指標+字首和>解決子陣列和排序後的區間和指標陣列排序
- POJ 2528 Mayor's posters (線段樹 區間更新+離散化)
- HDU 1556【區間更新+單點查詢 樹狀陣列】陣列
- 樹狀陣列陣列
- LeetCode 2535[陣列元素和與數字和的絕對差值]LeetCode陣列
- POJ3468 A Simple Problem with Integers---樹狀陣列(區間問題)陣列
- 解析樹狀陣列陣列
- HDU1166 敵兵佈陣【樹狀陣列 單點修改+區間查詢】陣列
- 差分陣列原理與其字首和的應用陣列
- 洛谷P1712 [NOI2016]區間 尺取法+線段樹+離散化
- leetcode 3366. 最小陣列和LeetCode陣列
- 二維樹狀陣列陣列
- 樹狀陣列詳解陣列
- 樹狀陣列基礎陣列
- 2024年暑假關於線段樹和樹狀陣列的小知識點陣列
- LeetCode C++ 劍指 Offer 51. 陣列中的逆序對【歸併排序/樹狀陣列/線段樹】LeetCodeC++陣列排序
- 【ACM演算法競賽日常訓練】DAY16【奇♂妙拆分】【區區區間間間】【小AA的數列】數學 | 位運算 | 字首和ACM演算法
- 洛谷題單指南-字首和差分與離散化-P1496 火燒赤壁
- AcWing 242. 一個簡單的整數問題(樹狀陣列解法)陣列
- LeetCode53. 最大子陣列和LeetCode陣列
- 樹狀陣列快速入門陣列
- 【筆記/模板】樹狀陣列筆記陣列
- golang切片和陣列的區別Golang陣列
- LeetCode-兩個排序陣列的中位數LeetCode排序陣列