acwing-802. 區間和
阿新 • • 發佈:2022-01-24
假定有一個無限長的數軸,數軸上每個座標上的數都是 0。
現在,我們首先進行 n 次操作,每次操作將某一位置 x 上的數加 c。
接下來,進行 m 次詢問,每個詢問包含兩個整數 l 和 r,你需要求出在區間 [l,r] 之間的所有數的和。
輸入格式
第一行包含兩個整數 n 和 m。
接下來 n 行,每行包含兩個整數 x 和 c。
再接下來 m 行,每行包含兩個整數 l 和 r。
輸出格式
共 m 行,每行輸出一個詢問中所求的區間內數字和。
資料範圍
−10^9≤ x ≤10^9,
1≤ n,m ≤10^5,
−10^9≤ l≤r ≤10^9,
−10000≤ c ≤10000
輸入樣例:
3 3 1 2 3 6 7 5 1 3 4 6 7 8
輸出樣例:
8
0
5
方法一:
被難住了..不熟悉C++ STL,故知道離散化和排序但不會去重 23333
分析:
- 數軸是無限長的,所以x∈R,所以不能開個陣列並且下標代表x,而輸入的x個數是有限的,所以可以將其離散化,比如
1 20 100 12312
對映到陣列下標1 2 3 4
- 這題要進行有序的離散化,也就是離散化之後用於對映的陣列儲存的x是有序的,便於後面使用二分搜尋
- 最後利用字首和進行求區間和操作
做法:
- 將輸入資料全部讀入,
alls
用來對映 ( 陣列下標, x ),即先把所有x讀入alls,再用STL函式排序和去重得到正確的對映資料 - 用
nums
儲存每個x上對應的c - 最後字首和,即區間和
補充:
find()
函式返回大於x的最小元素下標(當x大於最大元素,返回最大元素下標)- 核心在於理解離散化
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> PII; int n, m; int nums[300010]; vector<int> alls; vector<PII> add, query; int find(int x) { int l = 0, r = alls.size() - 1; while (l < r) { int mid = (l + r) >> 1; if (alls[mid] >= x) r = mid; else l = mid + 1; } return r + 1; } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { int x, c; scanf("%d%d", &x, &c); alls.push_back(x); add.emplace_back(x, c); } for (int i = 0; i < m; i++) { int l, r; scanf("%d%d", &l, &r); alls.push_back(l); alls.push_back(r); query.emplace_back(l, r); } // 排序+去重 sort(alls.begin(), alls.end()); alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 處理插入 for (auto item: add) { int x = find(item.first); nums[x] += item.second; } // 字首和 for (int i = 1; i <= alls.size(); i++) nums[i] += nums[i-1]; for (int i = 0; i < m; i++) { int l = find(query[i].first); int r = find(query[i].second); printf("%d\n", nums[r] - nums[l-1]); } }