As is known to all, the blooming time and duration varies between different kinds of flowers. Now there is a garden planted full of flowers. The gardener wants to know how many flowers will bloom in the garden in a specific time. But there are too many flowers in the garden, so he wants you to help him.
Input
The first line contains a single integer t (1 <= t <= 10), the number of test cases.
For each case, the first line contains two integer N and M, where N (1 <= N <= 10^5) is the number of flowers, and M (1 <= M <= 10^5) is the query times.
In the next N lines, each line contains two integer Si and Ti (1 <= Si <= Ti <= 10^9), means i-th flower will be blooming at time [Si, Ti].
In the next M lines, each line contains an integer Ti, means the time of i-th query.
Output
For each case, output the case number as shown and then print M lines. Each line contains an integer, meaning the number of blooming flowers.
Sample outputs are available for more details.
Sample Input
2
1 1
5 10
4
2 3
1 4
4 8
1
4
6
Sample Output
Case #1:
0
Case #2:
1
2
1
题意:
有n种花,每种有不同的开花时间,n行开花时间,下面m行是询问,问有几朵在开花
思路:
典型的树状数组,区间修改,定点询问,直接写是不行的,因为每个开花时间的范围1e9,连一个1e9的数组都开不了,所以就只能用离散化。先定义一个结构体,里面存着当前的x和下标id,这道题可以吧询问一起存进去,然后按x升序排列,这是下标被打乱,但是用a[]来跟他们从新编号,内容是下标,这样相邻的两个就是开花区间,这是用树状数组维护,因为存的时候吧询问都存进去了,在后面a编号是,询问也有一个编号,接下来直接输出getsum(询问的编号)
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 300005;
struct ac {
int x, id;
bool operator < (const ac &a) const {
return x < a.x;
}
} p[maxn];
int c[maxn], a[maxn];
void updata(int x, int v) {
while(x <= maxn) {
c[x] += v;
x += x & -x;
}
}
int getsum(int x) {
int res = 0;
while (x > 0) {
res += c[x];
x -= x & -x;
}
return res;
}
int main() {
int T, cnt = 0;
scanf("%d", &T);
while(T --) {
int n, m;
scanf("%d %d ", &n, &m);
int nn = n * 2;
int N = nn + m;
for (int i = 0; i < N; i ++) {//把所有全都存进去
scanf("%d", &p[i].x);
p[i].id = i;//每一个i都有一个标号
}
sort(p, p + N);//对.x排序
int k = 1;//从新编号
a[p[0].id] = k;
for (int i = 1; i < N; i ++) {
if (p[i].x == p[i - 1].x)
a[p[i].id] = k;
else
a[p[i].id] = ++k;
}
//按照x升序编号,但是在a中显示的是p[i].id,这样每一个数组的位置不变,但都得到了一个新的编号
//这个编号也可以看成简单树状数组里的位置,
//因为id决定顺序不变,但是k看成新的位置,是不是好理解一点,
//这样询问的位置就在已经维护好的树状数组中)
memset(c, 0, sizeof(c));
for (int i = 0; i < nn - 1; i += 2) {//维护树状数组
updata(a[i], 1);
updata(a[i + 1] + 1, -1);
}
printf("Case #%d:\n", ++cnt);
for (int i = nn; i < N; i ++) {
printf("%d\n", getsum(a[i]));//直接输出
}
}
return 0;
}