题目大意:给定n的区间和m的询问,每次询问求出有多少个区间包含所给出的点;
题目解析:用线段树做,把叶子节点想象成端点,并且维护cover即被几个区间所包含;这样需要把所有端点都sort一下,因为端点数值太大,需要离散化一下并且去重,找的时候因为排过序了所以只要二分搜索一下就ok了;初始化线段树的时候把所有区间所对应的index二分出来来进行更新;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=150010;
int cover[maxn<<2],list[maxn];
int q[50010],cnt;
struct node
{
int a,b;
}s[maxn];
void pushdown(int rt)
{
if(cover[rt]==0) return ;
cover[rt<<1]+=cover[rt];
cover[rt<<1|1]+=cover[rt];
cover[rt]=0;
}
void build(int l,int r,int rt)
{
cover[rt]=0;
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int le,int ri,int l,int r,int rt)
{
if(le<=l&&ri>=r)
{
cover[rt]+=1;
return ;
}
pushdown(rt);
int m=(l+r)>>1;
if(m>=le) update(le,ri,lson);
if(m<ri) update(le,ri,rson);
}
int query(int pos,int l,int r,int rt)
{
if(l==r)
{
return cover[rt];
}
pushdown(rt);
int m=(l+r)>>1;
if(m>=pos) return query(pos,lson);
else return query(pos,rson);
}
int search(int a)
{
int ans,l=1,r=cnt;
while(l<=r)
{
int m=(l+r)>>1;
if(list[m]<a)
{
l=m+1;
}
else
{
r=m-1;
ans=m;
}
}
return ans;
}
int main()
{
int cas,c,i,n,m;
scanf("%d",&cas);
for(c=1;c<=cas;c++)
{
scanf("%d%d",&n,&m);
cnt=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&s[i].a,&s[i].b);
list[++cnt]=s[i].a;
list[++cnt]=s[i].b;
}
for(i=1;i<=m;i++)
{
scanf("%d",&q[i]);
list[++cnt]=q[i];
}
int temp=0;
list[0]=-1;
sort(list+1,list+1+cnt);
for(i=1;i<=cnt;i++)
{
if(list[i]!=list[i-1])
{
list[++temp]=list[i];
}
}
cnt=temp;
build(1,cnt,1);
for(i=1;i<=n;i++)
{
update(search(s[i].a),search(s[i].b),1,cnt,1);
}
printf("Case %d:\n",c);
for(i=1;i<=m;i++)
{
printf("%d\n",query(search(q[i]),1,cnt,1));
}
}
return 0;
}