zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    锚点
    DOM
    background
    Vue前端路由
    JavaScript常用方法
    算法——dfs介绍
    时间复杂度和空间复杂度
    CSS定位(position)
    CSS三栏布局
    前端笔试高频知识点汇总
  • 原文地址:https://www.cnblogs.com/shutdown113/p/9364882.html
Copyright © 2011-2022 走看看