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: ",++cas); 121 for(i=1;i<=m;i++) 122 if(ansr[i]-ansl[i]>0) 123 printf("%d ",ansr[i]-ansl[i]); 124 else printf("0 "); 125 } 126 return 0; 127 }