【题目描述】
给定n个区间表示某种花开放的时间,询问在某一个时刻有多少种花开放。
【分析】
线段树的染色问题,询问即为某点被染色的次数。
这题的范围为10^9,需要离散化处理(ps.这题数据很弱,不离散化好像也能过的)。
对于离散化,我的做法是把输入的区间端点和询问的一起离散化,然后在进行线段树的操作。
维护的时候可以用懒惰标记的办法处理。
我的方法没有使用懒惰标记,更新的时候如果找到一个被完全覆盖的区间,那就更新这个区间,其他的区间就不更新,
询问的时候只要从线段树的根节点一直遍历到询问点就行,对这个路径上所有的区间值加和即可。
【关于离散化】
X[]数组存储需要离散化的值,然后排序,去掉值相同的点,再利用二分查找来找到某个值离散化之后所对应的值。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
#define lson l,m,n<<1
#define rson m+1,r,n<<1|1
using namespace std;
int s[N<<2];
int X[N<<2];
int ans;
int ss[N][2];
int q[N];
void update(int ll,int rr,int l,int r,int n){
if(ll==l&&rr==r){
s[n]++;
return;
}
int m=(l+r)>>1;
if(rr<=m)
update(ll,rr,lson);
else if(ll>m)
update(ll,rr,rson);
else
update(ll,m,lson),update(m+1,rr,rson);
}
void query(int nn,int l,int r,int n){
ans+=s[n];
if(l==r)return;
int m=(l+r)>>1;
if(nn<=m)
query(nn,lson);
else
query(nn,rson);
}
int BS(int k,int n,int *X){
int l=1,r=n;
while(l<=r){
int m=(l+r)>>1;
if(k==X[m]) return m;
else if(k<X[m]) r=m-1;
else l=m+1;
}
return -1;
}
int main(){
int n,m;
int d=1;
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
memset(s,0,sizeof(s));
int w=1;
X[w++]=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&ss[i][0],&ss[i][1]);
X[w++]=ss[i][0];
X[w++]=ss[i][1];
}
for(int i=1;i<=m;i++){
scanf("%d",&q[i]);
X[w++]=q[i];
}
X[w++]=10e9+1;
sort(X+1,X+w);
int k=2;
for(int i=2;i<w;i++){
if(X[i]!=X[i-1]) X[k++]=X[i];
}
for(int i=1;i<=n;i++){
int l=BS(ss[i][0],k-1,X);
int r=BS(ss[i][1],k-1,X);
update(l,r,1,k-1,1);
}
printf("Case #%d:\n",d++);
for(int i=1;i<=m;i++){
int nn=BS(q[i],k-1,X);
ans=0;
query(nn,1,k-1,1);
printf("%d\n",ans);
}
}
return 0;
}
浙公网安备 33010602011771号