題目描述
假定有一個無限長的數軸,數軸上每個座標上的數都是0。
現在,我們首先進行 n 次操作,每次操作將某一位置x上的數加c。
近下來,進行 m 次詢問,每個詢問包含兩個整數l和r,你需要求出在區間[l, r]之間的所有數的和。
輸入格式
第一行包含兩個整數n和m。
接下來 n 行,每行包含兩個整數x和c。
再接下里 m 行,每行包含兩個整數l和r。
輸出格式
共m行,每行輸出一個詢問中所求的區間內數字和。
數據範圍
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
輸入樣例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
輸出樣例:
8
0
5
思路:標準的離散化,給的數據和範圍很大,但總共也只有n個數,所以可以給這n這數就行重新編號。
代碼如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
typedef pair<int, int> p;
int a[N], sum[N];
p arr[N], query[N];
int n ,m;
vector<int>alls; //重新編號
int Find(int x) //查找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()
{
int l ,r ;
cin >>n >> m;
for(int i = 0; i < n; i++){
cin >> arr[i].first >> arr[i].second;
alls.push_back(arr[i].first);
}
for(int i = 0; i < m; i++){
cin >> l >> r;
query[i].first = l;
query[i].second = r;
alls.push_back(l);
alls.push_back(r);
}
//重新編號:去重和排序
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
for(int i = 0; i < n; i++){
int x = Find(arr[i].first);
a[x] += arr[i].second;
}
for(int i = 1; i <= alls.size(); i++)
sum[i] = sum[i - 1] + a[i];
for(int i = 0; i < m; i++){
int l = Find(query[i].first);
int r = Find(query[i].second);
cout << sum[r] - sum[l - 1] << endl;
}
return 0;
}