Description
给出n朵花的绽放时刻与凋谢时刻,并给出m次查询,每次查询一个时刻有多少朵花同时开放
Input
第一行为一整数t表示用例组数,每组用例第一行为两个整数n和m分别表示花的数量和查询的次数,之后n行每行两个整数s和e分别表示该朵花的绽放时刻和凋谢时刻,最后m行每行一个整数x表示查询在x时刻有多少朵花同时开放(1<=t<=10,1<=n,m<=10^5,1<=s<=e<=10^9)
Output
对于每次查询,输出查询结果
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
Solution
将所有花的绽放时刻,凋谢时刻以及查询的时刻放在一起排序后离散化建线段树,那么每朵花的开放就是对线段树的区间覆盖,查询就是对线段树的单点更新,注意离散化的时候要通过增点来去重
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 111111
struct Tree
{
int left,right,sum,flag;
}T[4*maxn];
int t,n,m,s[maxn],e[maxn],cnt,x[4*maxn],q[maxn];
void build(int l,int r,int t)
{
T[t].left=l;
T[t].right=r;
T[t].sum=T[t].flag=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(l,mid,2*t);
build(mid+1,r,2*t+1);
}
void push_up(int t)
{
T[t].sum=T[2*t].sum+T[2*t+1].sum;
}
void push_down(int t)
{
if(T[t].flag)
{
T[2*t].flag+=T[t].flag;
T[2*t+1].flag+=T[t].flag;
T[2*t].sum+=(T[2*t].right-T[2*t].left+1)*T[t].flag;
T[2*t+1].sum+=(T[2*t+1].right-T[2*t+1].left+1)*T[t].flag;
T[t].flag=0;
}
}
void update(int l,int r,int z,int t)
{
if(T[t].left==l&&T[t].right==r)
{
T[t].flag+=z;
T[t].sum+=(r-l+1)*z;
return ;
}
push_down(t);
if(r<=T[2*t].right) update(l,r,z,2*t);
else if(l>=T[2*t+1].left) update(l,r,z,2*t+1);
else
{
update(l,T[2*t].right,z,2*t);
update(T[2*t+1].left,r,z,2*t+1);
}
push_up(t);
}
int query(int tar,int t)
{
if(T[t].left==tar&&T[t].right==tar) return T[t].sum;
push_down(t);
if(tar<=T[2*t].right) return query(tar,2*t);
return query(tar,2*t+1);
}
int get(int tar)
{
return lower_bound(x,x+cnt,tar)-x+1;
}
int main()
{
int res=1;
scanf("%d",&t);
while(t--)
{
cnt=0;
printf("Case #%d:\n",res++);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s[i],&e[i]);
x[cnt++]=s[i],x[cnt++]=e[i];
}
for(int i=1;i<=m;i++)
{
scanf("%d",&q[i]);
x[cnt++]=q[i];
}
//离散化
sort(x,x+cnt);
cnt=unique(x,x+cnt)-x;
for(int i=cnt-1;i>0;i--)
if(x[i]-x[i-1]>1) x[cnt++]=x[i-1]+1;
sort(x,x+cnt);
build(1,cnt,1);
for(int i=1;i<=n;i++)
{
int l=get(s[i]),r=get(e[i]);//二分搜索到这朵花的绽放与凋谢时间
update(l,r,1,1);//覆盖这朵花的开放区间
}
for(int i=1;i<=m;i++)
{
int tar=get(q[i]);//二分搜索到这个查询时刻是树中哪个节点
printf("%d\n",query(tar,1));
}
}
return 0;
}