• 【bzoj4627】[BeiJing2016]回转寿司 离散化+树状数组


    题目描述

    给出一个长度为n的序列,求所有元素的和在[L,R]范围内的连续子序列的个数。

    输入

    第一行包含三个整数N,L和R,分别表示寿司盘数,满意度的下限和上限。
    第二行包含N个整数Ai,表示小Z对寿司的满意度。
    N≤100000,|Ai|≤100000,0≤L, R≤10^9

    输出

    仅一行,包含一个整数,表示共有多少种选择可以使得小Z的满意度之和
    不低于L且不高于R。

    样例输入

    5 5 9
    1 2 3 4 5

    样例输出

    6


    题解

    离散化+树状数组

    把序列和转化为前缀相减,即选出满足$Lle sum[x]-sum[y]le R$的$x>y$的数对个数。

    那么我们枚举$x$,即可得到$y$的范围,要求的是以前的满足条件的$y$的个数。可以维护1到当前位置树状数组,在树状数组中查询个数,最后再把该数加入到树状数组中。由于数据范围大,因此需要离散化。

    时间复杂度$O(nlog n)$

    #include <cstdio>
    #include <algorithm>
    #define N 100010
    #define now v + 1 , v + n + 2
    using namespace std;
    typedef long long ll;
    ll sum[N] , v[N];
    int f[N] , n;
    inline void add(int x)
    {
        int i;
        for(i = x ; i <= n + 1 ; i += i & -i) f[i] ++ ;
    }
    inline int query(int x)
    {
        int i , ans = 0;
        for(i = x ; i ; i -= i & -i) ans += f[i];
        return ans;
    }
    int main()
    {
        int i;
        ll l , r , ans = 0;
        scanf("%d%lld%lld" , &n , &l , &r);
        for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &sum[i]) , sum[i] += sum[i - 1] , v[i] = sum[i];
        sort(now);
        for(i = 0 ; i <= n ; i ++ ) ans += query(upper_bound(now , sum[i] - l) - v - 1) - query(lower_bound(now , sum[i] - r) - v - 1) , add(lower_bound(now , sum[i]) - v);
        printf("%lld
    " , ans);
        return 0;
    }
    

     

  • 相关阅读:
    rabbitmq在ios中实战采坑
    网络七层架构一句话简述
    HystrixCommand实战
    前端SEO技巧
    前端面试-难点问题2-java和javascript的区别
    前端面试题--难点问题
    [微信营销企划之路]003.Access forbidden!
    [Python进阶]001.不定参数
    [安卓基础]011存储数据(中)——sqlite语法介绍
    [JavaWeb基础] 015.Struts2 表单验证框架
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7662744.html
Copyright © 2020-2023  润新知