HDU 4417 Super Mario
题意: 知道了n 个连续位置处砖块的高度,有m个如下询问
l r h :区间[l,r] 中高度小于等于h的砖块有多少个。
分析: 用树状数组离线处理砖块的高度,对砖块按高度从低到高排序,
对询问按 h 从低到高排序,因为高度较小的砖块 不会影响跳
跃高度较大时候的答案,所以可以依次加入砖块,求出每个区间
的数目。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define clr(x)memset(x,0,sizeof(x)) #define maxn 100005 struct wall { int v,xu; }w[maxn]; struct node { int l,r,h,xu,res; }q[100005]; int cmp1(wall a,wall b) { return a.v<b.v; } int cmp2(node a,node b) { return a.h<b.h; } int cmp3(node a,node b) { return a.xu<b.xu; } int c[maxn]; int n; int lowbit(int x) { return (x)&(-x); } void add(int pos) { while(pos<=n) { c[pos]+=1; pos+=lowbit(pos); } } int sum(int pos) { if(pos<0) return 0; int s=0; while(pos>0) { s+=c[pos]; pos-=lowbit(pos); } return s; } int main() { int t,m,i,j,ca=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); clr(c); for(i=1;i<=n;i++) { scanf("%d",&w[i].v); w[i].xu=i; } sort(w+1,w+1+n,cmp1); for(i=0;i<m;i++) { scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h); q[i].l++; q[i].r++; q[i].xu=i; } sort(q,q+m,cmp2); j=1; for(i=0;i<m;i++) { while(w[j].v<=q[i].h&&j<=n) { add(w[j].xu); j++; } q[i].res=sum(q[i].r)-sum(q[i].l-1); } sort(q,q+m,cmp3); printf("Case %d:\n",ca++); for(i=0;i<m;i++) printf("%d\n",q[i].res); } return 0; }