hdu4417

题解:

主席树,查找前y+1个,减去前x个

当然也可以树状数组+离线

细节注意处理(当h小于任何一个数和没有出现过的时候)

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100005;
int rt[N],a[N],n,t,z,m,b[N],x,cnt,now,y,k;
struct Tree
{
    int num,ls,rs;
}T[20*N];
int ef(int x)
{
    int l=0,r=cnt;
    while (l<r)
     {
         int mid=(l+r+1)/2;
         if (b[mid]>x)r=mid-1;
         else l=mid;
     }
    return l; 
}
int build(int l,int r)
{
    now++;
    if (l==r)return now;
    int k=now;
    int mid=(l+r)/2;
    if (l<=mid)T[k].ls=build(l,mid);
    if (mid<r)T[k].rs=build(mid+1,r);
    return k;
}
int insert(int x,int l,int r,int s)
{
    now++;
    if (l==r)
     {
        T[now].num=T[x].num+1;
        return now;
     }
    int k=now,mid=(l+r)/2;
    if (s<=mid)
     {
         T[k].ls=insert(T[x].ls,l,mid,s);
         T[k].rs=T[x].rs;
     }
    else
     {
         T[k].ls=T[x].ls;
         T[k].rs=insert(T[x].rs,mid+1,r,s);
     }
    T[k].num=T[T[k].ls].num+T[T[k].rs].num;
    return k;
}
int find(int x,int y,int l,int r)
{
    if (l==r)return l<=y?T[x].num:0;
    if (r<=y)return T[x].num;
    int mid=(l+r)/2,ans=find(T[x].ls,y,l,mid);
    if (mid<y&&mid!=r)ans+=find(T[x].rs,y,mid+1,r);
    return ans;
}
int main()
{
    scanf("%d",&t);
    for (int cas=1;cas<=t;cas++)
     {
         printf("Case %d:
",cas);
         scanf("%d%d",&n,&m);
         memset(T,0,sizeof T);
         now=0;
         for (int i=1;i<=n;i++)scanf("%d",&a[i]);
         for (int i=1;i<=n;i++)b[i]=a[i];
         cnt=1;
         sort(b+1,b+n+1);
         for (int i=2;i<=n;i++)
          if (b[i-1]!=b[i])b[++cnt]=b[i];
         rt[0]=build(1,cnt);
        for (int i=1;i<=n;i++)rt[i]=insert(rt[i-1],1,cnt,ef(a[i])); 
         while (m--)
          {
              scanf("%d%d%d",&x,&y,&z);
              int k=ef(z);
              if (k==0)puts("0");else 
            printf("%d
",find(rt[y+1],k,1,cnt)-find(rt[x],k,1,cnt));
          }
     }
}
原文地址:https://www.cnblogs.com/xuanyiming/p/7905597.html