hdu4417(分塊+二分)
阿新 • • 發佈:2018-11-12
題目:
給n個數,數中有重複的。有m個詢問,問的是[L,R] 區間內有多少個數小於等於h。
分析:
快速查詢——排序(快排),二分
注意:
二分邊界
#include<bits/stdc++.h> #define maxn 100010 using namespace std; int n,m,num,block; int a[maxn],b[maxn],pos[maxn],ls[maxn],rs[maxn]; void reset(int k){ int l=(k-1)*block+1,r=min(k*block,n); sort(b+l,b+r+1); ls[k]=l;rs[k]=r; return ; } void work(int x,int y,int h){ int ans=0; if(pos[x]==pos[y]){ for(int i=x;i<=y;i++)if(a[i]<=h)ans++; printf("%d\n",ans); return ; } for(int i=pos[x]+1;i<=pos[y]-1;i++){ int left=ls[i],right=rs[i],mid; while(left<=right){ mid=(left+right)/2; if(b[mid]<=h)left=mid+1; if(b[mid]>h)right=mid-1; } ans=ans+right-ls[i]+1; } for(int i=x;i<=rs[pos[x]];i++)if(a[i]<=h)ans++; for(int i=ls[pos[y]];i<=y;i++)if(a[i]<=h)ans++; printf("%d\n",ans); return ; } int main(){ int t; scanf("%d",&t); for(int j=1;j<=t;j++){ printf("Case %d:\n",j); scanf("%d %d",&n,&m); block=sqrt(n*1.0); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); pos[i]=(i-1)/block+1; b[i]=a[i]; } num=n/block;if(n%block!=0)num++; for(int i=1;i<=num;i++)reset(i); for(int i=1;i<=m;i++){ int l,r,h; scanf("%d %d %d",&l,&r,&h); work(l+1,r+1,h); } } return 0; }