线段树的区间更新和单点查询。需要注意的是要把区间端点和查询的点都先读入并离散化。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
const int maxn = 100100;
int tcase, n, m;
int sum[maxn<<2], add[maxn<<2];
int s[maxn], t[maxn], q[maxn];
map<int, int> mp;
int Time[maxn*3];
void pushDown(int rt)
{
if (add[rt]) {
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt];
sum[rt<<1|1] += add[rt];
add[rt] = 0;
}
}
void build(int l, int r, int rt)
{
sum[rt] = 0;
add[rt] = 0;
if (l == r) return ;
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
}
void update(int l, int r, int rt, int L, int R)
{
if (L <= l && R >= r) {
add[rt] += 1;
sum[rt] += 1;
return ;
}
pushDown(rt);
int m = (l + r) >> 1;
if (L <= m) {
update(l, m, rt << 1, L, R);
}
if (R > m) {
update(m + 1, r, rt << 1 | 1, L, R);
}
}
int query(int l, int r, int rt, int p)
{
if (l == r) {
return sum[rt];
}
pushDown(rt);
int m = (l + r) >> 1;
if (p <= m) {
return query(l, m, rt << 1, p);
} else {
return query(m + 1, r, rt << 1 | 1, p);
}
}
int main()
{
scanf("%d", &tcase);
for (int cas = 1; cas <= tcase; ++cas) {
printf("Case #%d:\n", cas);
scanf("%d%d", &n, &m);
int id = 0;
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &s[i], &t[i]);
Time[++id] = s[i];
Time[++id] = t[i];
}
for (int i = 1; i <= m; ++i) {
scanf("%d", &q[i]);
Time[++id] = q[i];
}
sort(Time + 1, Time + id + 1);
int cnt = 0;
Time[++cnt] = Time[1];
for (int i = 2; i <= id; ++i) {
if (Time[i] != Time[cnt]) {
Time[++cnt] = Time[i];
}
}
for (int i = 1; i <= cnt; ++i) {
mp[Time[i]] = i;
}
build(1, cnt, 1);
for (int i = 1; i <= n; ++i) {
update(1, cnt, 1, mp[s[i]], mp[t[i]]);
}
for (int i = 1; i <= m; ++i) {
printf("%d\n", query(1, cnt, 1, mp[q[i]]));
}
}
return 0;
}