Flowers
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/65536K (Java/Other)
Total Submission(s) : 2 Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
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 S i and T i (1 <= S i <= T i <= 10^9), means i-th flower will be blooming at time [S i, T i].
In the next M lines, each line contains an integer T i, means the time of i-th query.
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 S i and T i (1 <= S i <= T i <= 10^9), means i-th flower will be blooming at time [S i, T i].
In the next M lines, each line contains an integer T i, 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 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
题意:不同的花在不同时间段开放,问某个时间段有多少花开着。
思路:看题目我们就知道要把时间作为线段,通过输入的开放时间来更新区间,但是题目给出的时间单位时1~1^9,数组开不了那么大,所以得用离散化来解决这个问题。 离散化:(把很大的时间区间用比较小的值来保存,比如 100 25 300 40 ,就可以分别保存为3 1 4 2。这样就可以节省空间了,由于题目给的n时50000,所以时间最多最多只能分这么多区间,所以数组开500000就可以了。
把时间分区间的方法:首先每个点用结构体存,存它是第几朵花和它的时间点,然后先按时间从小到大排,然后给它一个id,用来时间分区,并且同时把你后面输入的查询时间也用相同的方法保存。然后用树状数组把点按花朵编号的顺序存进去,但给的时间是离散化后的时间,最后给出答案就好了。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 500000
int sum1[maxn],sum2[maxn],id;
struct Node{ //点的结构体
int num,pos;
}node[maxn];
int cmp(const Node &a,const Node &b){
return a.num < b.num; //升序排列
}
int getSum(int x){ // 统计区间数值
int sum = 0;
while(x > 0){
sum += sum1[x];
x -= x & -x;
}
return sum;
}
void update(int pos,int num){ // 把sum2里的数,就是时间点扔进来,把这个时间点之后的区间更新
while(pos <= id){
sum1[pos] += num;
pos += pos & -pos;
}
}
int main(){
int n,m,t,Case = 1;
scanf("%d",&t);
while(t--){
printf("Case #%d:\n",Case++);
scanf("%d %d",&n,&m);
int tn = n * 2;
int tm = tn + m;
for(int i = 0;i < tm;i++){
scanf("%d",&node[i].num);
node[i].pos = i;
}
sort(node,node + tm,cmp); //把所有输入进来的时间点按从小到大排序,然后分成小区间存sum2里
id = 1;
sum2[node[0].pos] = id; //第一个点就存1
for(int i = 1;i < tm;i++){ //把数离散化分成小的存在sum2里面
if(node[i].num == node[i - 1].num){ //若这个点与前一个点时间相同,则存同一个区间
sum2[node[i].pos] = id;
}else{ //不相同则存下一个区间
sum2[node[i].pos] = ++id;
}
}
memset(sum1,0,sizeof(sum1));
for(int i = 0;i < tn - 1;i++){
update(sum2[i++],1); //把前数扔进来,后面区间加一
update(sum2[i] + 1, -1); //后数扔进来,后面巨剑减一
}
for(int i = tn;i < tm;i++){
printf("%d\n",getSum(sum2[i])); //sum2[i]指的时那个时间点的离散化后的时间点,找到这个时间点里存的值。
}
}
return 0;
}