/* 题意: 给你一个数列,然后有m次查询,每次查询一段区间 [l,r] 内不大于 h 的值的个数。 解法: 离线 树状数组 1、若 a[i].h > q[j].h,则从 i 以后的 a[i].h 也不会再对这个查询的解有影响。此时我们可以得到这个查询的解 getsum(r) - getsum(l-1) 。 2、若 a[i].h <= q[j].h,则它会且仅会对从 j 以后的每个 q[j].h 产生影响。于是我们需要在区间中对这个位置加1,然后让 i 向后移动。 */ #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int N=100002; int d[N],ans[N],n; struct node { int l,r,h,id; }q[N],p[N]; int lowbit(int x) { return x&(-x); } int cmp(node a,node b) { return a.h<b.h; } void add(int x,int data) { for(;x<=n;x+=lowbit(x))d[x]+=data; //注意这里的n不一定是数据量。可能是数据中最大的一个 } int getsum(int x) { int ret=0; for(;x;x-=lowbit(x))ret+=d[x]; return ret; } int main() { int t,m,i,j,cas=1; cin>>t; while(t--) { memset(d,0,sizeof(d)); printf("Case %d:\n",cas++); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&p[i].h); p[i].id = i+1; } for(j=0;j<m;j++) { scanf("%d%d%d",&q[j].l,&q[j].r,&q[j].h); q[j].id = j; } sort(p,p+n,cmp); sort(q,q+m,cmp); for(j=i=0;j<m;j++) { while(i<n&&p[i].h<=q[j].h) { add(p[i].id,1); i++; } ans[q[j].id] = getsum(q[j].r+1) - getsum(q[j].l); } for(j=0;j<m;j++) printf("%d\n",ans[j]); } return 0; }