题意:
给N个数,M次询问,每次询问区间[L,R]内元素在[X,Y]内的个数。
思路:
和之前hdu4417一样,这里因为有要在[X,Y]区间内。
所以做两次求出[1,Y]和[1,X-1]内的元素个数,然后相减得出答案。
代码:
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#include"map"
#include"vector"
#define ll long long
using namespace std;
struct quary
{
int id,x,y,c,d;
} q[110000];
struct fuck
{
int id,s;
} v[105666];
struct node
{
int l,r;
int sum;
} a[200031*4];
int mark[200021],ans[105555][2];
int cmp(fuck a,fuck b)
{
return a.s<b.s;
}
int cmp1(quary a,quary b)
{
return a.d<b.d;
}
int cmp2(quary a,quary b)
{
return a.c<b.c;
}
void init(int id,int l,int r)
{
a[id].l=l;
a[id].r=r;
a[id].sum=0;
if(l==r) return ;
int mid=(l+r)/2;
init(id*2,l,mid);
init(id*2+1,mid+1,r);
}
void updata(int id,int x,int y)
{
if(a[id].l==a[id].r && a[id].l==x)
{
a[id].sum+=y;
return ;
}
int mid=(a[id].l+a[id].r)/2;
if(x<=mid) updata(id*2,x,y);
else updata(id*2+1,x,y);
a[id].sum=a[2*id].sum+a[2*id+1].sum;
}
int qcont(int id,int x,int y)
{
if(a[id].l==x && a[id].r==y) return a[id].sum;
int mid=(a[id].l+a[id].r)/2;
if(y<=mid) return qcont(2*id,x,y);
else if(x>mid) return qcont(2*id+1,x,y);
else return qcont(2*id,x,mid)+qcont(2*id+1,mid+1,y);
}
int main()
{
int t,cas=1;
cin>>t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d",&v[i].s);
v[i].id=i;
}
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d",&q[i].x,&q[i].y,&q[i].c,&q[i].d);
q[i].id=i;
}
sort(v+1,v+1+n,cmp);
sort(q,q+m,cmp1);
init(1,1,n);
int j=1;
for(int i=0; i<m; i++)
{
while(j<=n && v[j].s<=q[i].d)
{
updata(1,v[j].id,1);
j++;
}
ans[q[i].id][0]=qcont(1,q[i].x,q[i].y);
}
sort(q,q+m,cmp2);
init(1,1,n);
j=1;
for(int i=0; i<m; i++)
{
while(j<=n && v[j].s<q[i].c)
{
updata(1,v[j].id,1);
j++;
}
ans[q[i].id][1]=qcont(1,q[i].x,q[i].y);
}
printf("Case #%d:\n",cas++);
for(int i=0; i<m; i++) printf("%d\n",ans[i][0]-ans[i][1]);
}
return 0;
}