题意:
给出区间[s,t],区间里面的每个数都加一,最后单点查询,给出的区间范围较大。
分析:
离散化后每个值用下标进行代替。缩小了区间范围。然后就可以套用树状数组板子了。但是其实原理还是差分,不过树状数组求前缀和快了点,但是自己写完后发现树状数组跟手写前缀和时间一样。可能是中间二分查询的时候不够优化吧。不过还可以,都是280ms
1.离散化+差分。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
int x,y;
}p[maxn];
int t[maxn*3],f[maxn<<1];
int main(){
int T;
scanf("%d",&T);
for(int cs=1;cs<=T;cs++){
memset(f,0,sizeof f);
int n,m;
scanf("%d%d",&n,&m);
int len=0;
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
t[len++]=p[i].x;
t[len++]=p[i].y;
t[len++]=p[i].x-1;
}
sort(t,t+len);
len=unique(t,t+len)-t;
int Max=0;
for(int i=0;i<n;i++){
int x=lower_bound(t,t+len,p[i].x)-t;
f[x]++;
x=lower_bound(t,t+len,p[i].y)-t;
f[x+1]--;
Max=max(Max,x+1);
}
for(int i=1;i<=Max;i++){
f[i]+=f[i-1];
}
printf("Case #%d:\n",cs);
while(m--){
int x;
scanf("%d",&x);
x=lower_bound(t,t+len,x)-t;
printf("%d\n",f[x]);
}
}
return 0;
}
2.离散化+树状数组
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int c1[maxn],n,m,val,x,y,temp;
int f[maxn*3],q[maxn];
struct node{
int l,r;
}p[maxn];
inline int lowbit(int x){
return x&-x;
}
void update(int x,int val)
{
while(x<maxn)
{
c1[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x)
{
ans+=c1[x];
x-=lowbit(x);
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
for(int cs=1;cs<=T;cs++){
memset(c1,0,sizeof c1);
scanf("%d%d",&n,&m);
int len=1;
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].l,&p[i].r);
f[len++]=p[i].l;
f[len++]=p[i].r;
}
for(int i=1;i<=m;i++){
scanf("%d",&q[i]);
f[len++]=q[i];
}
sort(f+1,f+len);
len=unique(f+1,f+len)-f;
for(int i=1;i<=n;i++){
update(lower_bound(f+1,f+len,p[i].l)-f,1);
update(lower_bound(f+1,f+len,p[i].r)-f+1,-1);
}
printf("Case #%d:\n",cs);
for(int i=1;i<=m;i++){
printf("%d\n",sum(lower_bound(f+1,f+len,q[i])-f));
}
}
return 0;
}