Flowers
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1988 Accepted Submission(s): 981
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 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
这个题有三种解法。线段树+离散化,直接用数组求解,暴力。
第一种线段树+离散化,最复杂的一种方法。这是我做的第一个线段树的题,WA了好多次,才A了。看代码吧
#include "iostream"
#include "cstdio"
#include "algorithm"
using namespace std;
#define lson n<<1
#define rson n<<1|1
#define maxn 100010
struct line{
int left, right;//左右端点
int n;//线段出现次数
}tree[maxn<<2];
int st[maxn], ed[maxn];
int q[maxn], data[maxn<<1];
//建立
void Build(int s, int t, int n)
{
tree[n].left = s;
tree[n].right = t;
tree[n].n = 0;
if(s == t) return;
int mid = (tree[n].left + tree[n].right)>>1;
Build(s, mid, lson);
Build(mid+1, t, rson);
}
void PushDown(int n)
{
if(tree[n].n > 0)
{
tree[lson].n += tree[n].n;
tree[rson].n += tree[n].n;
tree[n].n = 0;
}
}
//插入
void Insert(int s, int t, int n)//要插入线段的左右端点,以及当前线段树中的某条线段
{
if(s <= tree[n].left && t >= tree[n].right)
{
tree[n].n++; //插入线段匹配,次线段出现次数加1
return;
}
else
{
PushDown(n);
if(s <= tree[lson].right)
{
Insert(s, t, lson);
}
if(t >= tree[rson].left)
Insert(s, t, rson);
}
}
//访问
int Query(int index, int n)
{
if(tree[n].left == tree[n].right)
return tree[n].n;
else
{
PushDown(n);
if(index <= tree[lson].right)
return Query(index, lson);
else
return Query(index, rson);
}
}
int main()
{
int t, ti = 0;
scanf("%d", &t);
while(ti < t)
{
ti++;
int n, m, i, cnt = 0;
scanf("%d %d", &n, &m);
for(i = 0; i < n; i++)
{
scanf("%d %d", &st[i], &ed[i]);
data[cnt++] = st[i];
data[cnt++] = ed[i];
}
for(i = 0; i < m; i++)
{
scanf("%d", &q[i]);
data[cnt++] = q[i];
}
sort(data, data + cnt);
cnt = unique(data, data + cnt) - data;
Build(1, cnt, 1);
for(i = 0; i < n; i++)
{
st[i] = lower_bound(data, data + cnt, st[i]) - data + 1;
ed[i] = lower_bound(data, data + cnt, ed[i]) - data + 1;
Insert(st[i], ed[i], 1);
}
printf("Case #%d:\n", ti);
for(i = 0; i < m; i++)
{
q[i] = lower_bound(data, data + cnt, q[i]) - data + 1;
printf("%d\n", Query(q[i], 1));
}
}
return 0;
}
第二种方法,直接用数组求解。这是最简单,最巧妙,但也是最不容易想到的方法。看代码
#include "iostream"
#include "cstdio"
#include "algorithm"
using namespace std;
#define maxn 100010
int st[maxn], ed[maxn];
int main()
{
int t, ti;
scanf("%d", &t);
for(ti = 1; ti <= t; ti++)
{
int n, m, i;
scanf("%d %d", &n, &m);
for(i = 0; i < n; i++)
{
scanf("%d %d", &st[i], &ed[i]);
}
sort(st, st + n);
sort(ed, ed + n);
printf("Case #%d:\n", ti);
for(i = 0; i < m; i++)
{
int q, cnt;
scanf("%d", &q);
cnt = upper_bound(st, st + n, q) - st;
cnt -= lower_bound(ed, ed + n, q) - ed;
printf("%d\n", cnt);
}
}
return 0;
}
第三种方法,完全暴力,准确说是取巧的方法。感觉用这种方法过的人完全是靠运气。不过运气也是一种能力,不能不服。看代码就知道了。
#include "iostream"
#include "cstdio"
#include "vector"
#include "algorithm"
using namespace std;
int cnt[500005];
int main()
{
int t, ti = 0;
scanf("%d", &t);
while(ti < t)
{
ti++;
memset(cnt, 0, sizeof(cnt));
int n, m, i;
scanf("%d %d", &n, &m);
for(i = 0; i < n; i++)
{
int s, t;
scanf("%d %d", &s, &t);
int j;
for(j = s; j <= t; j++)
{
cnt[j]++;
}
}
printf("Case #%d:\n", ti);
for(i = 0; i < m; i++)
{
int temp;
scanf("%d", &temp);
printf("%d\n", cnt[temp]);
}
}
return 0;
}