1.双指针

2.位运算

3.离散化

1.区间和

「题解:」

  • 把所有坐标存到坐标数组 index_arr 中,并排序,去重
  • 之后在一个全为0 的数组 a 中,根据 find 函数寻找 x 在index_arr的下标值,然后根据下标值在a中进行加减操作。
  • 之后 进行前缀和,根据a中的数据进行前缀和。
  • 之后处理询问。

「注意事项:」

  • 在进行询问查找时,x对应的下标值必定存在数据不为0,因为明确对x进行的操作,但是 l,r不一定有值,但是一定存在 index_arr 数组里面占据一个位置。
  • 因为占据位置,所以 a 里面如果有 l,r对应,一定存在空缺 0,所以可以安心进行前缀和操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
int a[N] = {0},s[N]= {0};
typedef pair<int,int> PA;

vector<int> index_arr;
vector<PA> conderation_arr;
vector<PA> query_arr;

int find(int x)
{
int l = 0,r = index_arr.size() - 1;
while( l < r)
{
int mid = (l + r) / 2;
if(index_arr[mid] >= x )
{
r = mid;
} else
{
l = mid + 1;
}
}
// 下标从 1 开始
return r + 1;
}


int main()
{
int n,m;
cin >> n >> m;


// 1.存下标的数组 index_arr
// 2.存操作的数组 conderation_arr
// 3.存 操作后数据结果的 数组 a

for(int i = 0; i < n;++i)
{
int x,c;
cin >> x >> c;
conderation_arr.push_back({x,c}); // 操作记录数据集合
index_arr.push_back(x);

}

for(int i = 0; i < m;++i)
{
int l,r;
cin >> l >> r;
query_arr.push_back({l,r});
index_arr.push_back(l);
index_arr.push_back(r);

}
sort(index_arr.begin(),index_arr.end()); //坐标数组排序
index_arr.erase(unique(index_arr.begin(),index_arr.end()),index_arr.end()); // 去重

// 处理操作集 插入
for( auto item : conderation_arr)
{
int x = find(item.first); // 因为操作里的 x 是存在的,所以 对应的x下标值必然存在。
a[x] += item.second;
}
// 处理前缀和
for(int i = 1; i <= index_arr.size(); ++i)
{
s[i] = s[i-1] + a[i];
}
// 处理询问
for(auto item: query_arr)
{
int l = find(item.first);
int r = find(item.second);
int num = s[r] - s[l - 1];
cout << num << endl;
}
return 0;
}

4.区间合并