1 /*题目大意:输入一序列n个数字,然后输入m个询问,每个询问包含左边区间和右边区间,还有a和b,问你这个区间内有几个数大于等于a且小于等于b
2 做法:树状数组,先求出这个区间内有几个数小于a,然后求这个区间内有几个数小于等于b,拿后者减去前者就是答案了*/
3 #include<stdio.h>
4 #include<string.h>
5 #include<algorithm>
6 using namespace std;
7 const int maxn=50010;
8 int c[maxn],ansl[maxn],ansr[maxn];
9 struct pp
10 {
11 int num;
12 int id;
13 }p[maxn];
14 struct p2p
15 {
16 int hi;
17 int id;
18 int l,r;
19 int low;
20 }p1[maxn];
21 int cmp(pp a,pp b)
22 {
23 return a.num<b.num;
24 }
25 int cmp1(p2p a,p2p b)
26 {
27 return a.low<b.low;
28 }
29 int cmp2(p2p a,p2p b)
30 {
31 return a.hi<b.hi;
32 }
33 int n,m;
34 int lowbit(int x)
35 {
36 return x&(-x);
37 }
38 void add(int x,int d)
39 {
40 while(x<=n)
41 {
42 c[x]+=d;
43 x=x+lowbit(x);
44 }
45 }
46 int sum(int x)
47 {
48 int ans=0;
49 while(x>0)
50 {
51 ans+=c[x];
52 x=x-lowbit(x);
53 }
54 return ans;
55 }
56 int main()
57 {
58 int i,j,k;
59 int t;
60 int cas=0;
61 scanf("%d",&t);
62 while(t--)
63 {
64 memset(c,0,sizeof(c));
65 memset(ansl,0,sizeof(ansl));
66 scanf("%d%d",&n,&m);
67 for(i=1;i<=n;i++)
68 {
69 scanf("%d",&p[i].num);
70 p[i].id=i;
71 }
72 for(i=1;i<=m;i++)
73 {
74 scanf("%d%d%d%d",&p1[i].l,&p1[i].r,&p1[i].low,&p1[i].hi);
75 p1[i].id=i;
76 }
77 sort(p+1,p+n+1,cmp);
78 sort(p1+1,p1+m+1,cmp1);
79 i=1;
80 j=1;
81 while(j<=m)
82 {
83 while(i<=n)
84 {
85 if(p[i].num>=p1[j].low)
86 break;
87 add(p[i].id,1);
88 i++;
89 }
90 while(j<=m)
91 {
92 if(i<=n&&p[i].num<p1[j].low)
93 break;
94 ansl[p1[j].id]=sum(p1[j].r)-sum(p1[j].l-1);
95 j++;
96 }
97 }
98 i=1;
99 j=1;
100 memset(c,0,sizeof(c));
101 memset(ansr,0,sizeof(ansr));
102 sort(p1+1,p1+m+1,cmp2);
103 while(j<=m)
104 {
105 while(i<=n)
106 {
107 if(p[i].num>p1[j].hi)
108 break;
109 add(p[i].id,1);
110 i++;
111 }
112 while(j<=m)
113 {
114 if(i<=n&&p[i].num<=p1[j].hi)
115 break;
116 ansr[p1[j].id]=sum(p1[j].r)-sum(p1[j].l-1);
117 j++;
118 }
119 }
120 printf("Case #%d:\n",++cas);
121 for(i=1;i<=m;i++)
122 if(ansr[i]-ansl[i]>0)
123 printf("%d\n",ansr[i]-ansl[i]);
124 else printf("0\n");
125 }
126 return 0;
127 }