zoukankan      html  css  js  c++  java
  • hdu 4417 Super Mario (主席树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417

    题意:

    给你段长为n的序列,有q个询问,每次询问区间[l.r]内有多少个数小于等于k

    思路:

    之前用分块写过类似的,不过为了练习下主席树,这里用主席树写了下。思路很简单

    离线离散化处理下,每次插入一个数num时,在主席树上下标num+1,这样每次询问[l,r]中有多少个小于k的数的时候,我们只要找下标【1,k】的区间第R次修改后的总和减去第L-1次修改后的总值就可以得到了

    实现代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int M = 2e5+10;
    int ls[M*40],rs[M*40],sum[M*40],a[M],b[M],root[M];
    int idx;
    void build(int &k,int l,int r){
        k = ++idx;
        sum[k] = 0;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        build(ls[k],l,mid); build(rs[k],mid+1,r);
    }
    
    void update(int old,int &k,int l,int r,int p,int c){
        k = ++idx;
        ls[k] = ls[old]; rs[k] = rs[old];
        sum[k] = sum[old] + c;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        if(p <= mid) update(ls[old],ls[k],l,mid,p,c);
        else update(rs[old],rs[k],mid+1,r,p,c);
    }
    
    int query(int old,int k,int L,int R,int l,int r){
        if(L <= l&&R >= r) return sum[k] - sum[old];
        int mid = (l + r) >> 1;
        int ret = 0;
        if(L <= mid) ret += query(ls[old],ls[k],L,R,l,mid);
        if(R > mid) ret += query(rs[old],rs[k],L,R,mid+1,r);
        return ret;
    }
    int l[M],r[M],x[M],cnt;
    int Find(int x){
        int num = lower_bound(b+1,b+1+cnt,x)-b;
        return num;
    }
    
    int main()
    {
        int t,q,n,cas=1;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&q);
            for(int i = 1;i <= n;i ++)
                scanf("%d",&a[i]),b[i] = a[i];
            for(int i = 1;i <= q;i ++)
                scanf("%d%d%d",&l[i],&r[i],&x[i]),b[i+n]=x[i];
            sort(b+1,b+1+n+q);
            cnt = unique(b+1,b+1+n+q)-b-1;
            for(int i = 1;i <= n;i++){
                int fx = Find(a[i]);
                update(root[i-1],root[i],1,cnt,fx,1);
            }
            printf("Case %d:
    ",cas++);
            for(int i = 1;i <= q;i ++){
                int fx = Find(x[i]);
                printf("%d
    ",query(root[l[i]],root[r[i]+1],1,fx,1,cnt));
            }
        }
        return 0;
    }
  • 相关阅读:
    bzoj:1299: [LLH邀请赛]巧克力棒
    [51nod][cf468D]1558 树中的配对
    HDU5447 Good Numbers
    Timus Online Judge:ural:1006. Square Frames
    poj1830:开关问题
    bzoj:1776: [Usaco2010 Hol]cowpol 奶牛政坛
    bzoj:1725: [Usaco2006 Nov]Corn Fields牧场的安排
    bzoj:1828: [Usaco2010 Mar]balloc 农场分配
    bzoj:1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
    bzoj:1598: [Usaco2008 Mar]牛跑步
  • 原文地址:https://www.cnblogs.com/kls123/p/9568553.html
Copyright © 2011-2022 走看看