题意:
给N个数,M次询问。每次询问区间[L,R]内,小于等于H的数的个数。
思路:
离线操作线段树,将N个数与H排序。
每次读入小于等于H的数。
然后询问区间的和。
从而实现快速地解决问题。
代码:
#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;
}q[110000];
struct fuck
{
int id,s;
}v[105666];
struct node
{
int l,r;
int sum;
} a[200031*4];
int mark[200021],ans[105555];
int cmp(fuck a,fuck b)
{
return a.s<b.s;
}
int cmp1(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",&q[i].x,&q[i].y,&q[i].c);
q[i].x++;
q[i].y++;
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].c)
{
updata(1,v[j].id,1);
j++;
}
ans[q[i].id]=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]);
}
return 0;
}