hdu4417(主席树)

Super Mario

题意:

  求【l,r】区间内小于等于k的数的个数。

分析:

  首先考虑简单版,求【1,n】区间小于等于k的个数,如果一个数出现一次,就把对应的sum【rt】++,最后用线段树求一下【1,k】区间的sum之和就好了。所以我们可以用主席树来存储历史版本的线段树,然后对【l,r】区间对应的线段树求【1,k】区间的sum之和。

代码:

#include <map>
#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))
#define lson l,m
#define rson m+1,r

const int maxn=1e5+100;
const int inf=0x3f3f3f3f;

int n,m,tot,Case;

int a[maxn],Hash[maxn];
int L[maxn<<2],R[maxn<<2],T[maxn<<2],sum[maxn<<2];

int build(int l,int r)
{
    int rt=tot++;
    sum[rt]=0;
    if(l<r){
        int m=(l+r)>>1;
        L[rt]=build(lson);
        R[rt]=build(rson);
    }
    return rt;
}

int update(int pre,int l,int r,int x)
{
    int rt=tot++;
    L[rt]=L[pre];
    R[rt]=R[pre];
    if(l==r){
        sum[rt]=sum[pre]+1;
        return rt;
    }
    int m=(l+r)>>1;
    if(x<=m)    L[rt]=update(L[pre],lson,x);
    else        R[rt]=update(R[pre],rson,x);
    sum[rt]=sum[L[rt]]+sum[R[rt]];
    return rt;
}

int query(int u,int v,int ql,int qr,int l,int r)
{
    if(ql<=l&&r<=qr){
        return sum[v]-sum[u];
    }
    int ans=0;
    int m=(l+r)>>1;
    if(ql<=m)    ans+=query(L[u],L[v],ql,qr,lson);
    if(qr>m)     ans+=query(R[u],R[v],ql,qr,rson);
    return ans;
}

int binarySearch(int key,int* a,int n)
{
    if(a[1]>key)    return -1;
    if(a[n]<key)    return n;
    int l=1,r=n;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(a[mid]==key) return mid;
        if(a[mid]>key&&a[mid-1]<key)   return mid-1;
        else if(a[mid]<key) l=mid+1;
        else r=mid-1;
    }
    return -1;
}

int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d",&Case);
    for(int t=1;t<=Case;t++){
        tot=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            Hash[i]=a[i];
        }

        sort(Hash+1,Hash+n+1);
        int d=1;
        for(int i=2;i<=n;i++){
            if(Hash[i]!=Hash[i-1])    Hash[++d]=Hash[i];
        }
        T[0]=build(1,d);
        for(int i=1;i<=n;i++){
            int x=binarySearch(a[i],Hash,d);
            T[i]=update(T[i-1],1,d,x);
        }

        printf("Case %d:
",t);
        for(int i=1;i<=m;i++){
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            l++,r++;
            k=binarySearch(k,Hash,d);
            if(k==-1){
                printf("0
");
                continue;
            }
            int p=query(T[l-1],T[r],1,k,1,d);
            printf("%d
",p);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shutdown113/p/9364882.html