复习一波,发现了本题两个坑点。
一、找到离散化的编号后,判断所给区间在不在所有出现过的编号区间内
二、考虑下r编号tr,如果大于q[tr].x > r,说明右部区间超出了给定范围
为什么一个二分模板可以把两个部分编号都求出来?
两者得到的编号tl,tr都是大于等于l,r的编号
对于tr来说只需要特判情况二,对于tl来说q[tl].x >= l,所以减去的一定是a[tl-1]
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100010;
int n, m;
ll sum[N];
struct Node{
int num;
ll v;
bool operator < (const Node &A) const {
return num < A.num;
}
}p[N];
int b_s(int l, int r, int x) {
while(l < r) {
int mid = l + r >> 1;
if(p[mid].num >= x) r = mid;
else l = mid + 1;
}
return l;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
int x; ll c; scanf("%d%lld", &x, &c);
p[i] = {x, c};
}
sort(p + 1, p + 1 + n);
int g = 0;
for(int i = 1; i <= n; i++) {
p[++g] = p[i];
int j = i + 1;
while(j <= n && p[i].num == p[j].num) {
p[g].v += p[j].v;
j++;
}
i = j - 1;
}
for(int i = 1; i <= g; i++) sum[i] = sum[i - 1] + p[i].v;
//for(int i = 1; i <= g; i++) printf("%d %d\n", p[i].num, p[i].v);
while(m--) {
int l, r; scanf("%d%d", &l, &r);
int tl = b_s(1, g, l);
int tr = b_s(1, g, r);
if(r < p[1].num || l > p[g].num) puts("0");
else {
if(p[tr].num > r) tr--;
printf("%lld\n", sum[tr] - sum[tl - 1]);
}
}
return 0;
}