HDU 4325 Flowers(树状数组 + 离散化)

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;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/81169908