• 值域线段树and动态开线段树


    值域线段树每一个节点代表一个值,其他没什么区别

    动态开树就是节省了没有用到节点,其中重要一点的是不需要节点是连续的(即id值是任意的,只要可以找到即可)

    例题

    Bzoj 4627 回转寿司


    题意

    给n个数问区间和在L<=sum【r】-sum【l-1】<=R区间有多少个

    (N≤100000,|Ai|≤100000,0≤L, R≤10^9)


    分析

    由于区间和不单调,所以不能二分求取,分析可得推出公式   sum(r)-R<=sum(l-1)<=sum(r)-L  ([l,r]是一个满足条件的区间)

    直接计算当前前缀和之前满足条件的前缀和个数,累加起来则为答案

    故考虑利用线段树,每次让对应的前缀和加1,然后统计满足条件的个数,但是这个数最大可以达到1e10,不可能开这么大的空间,

    但N最大10w,和的种类也就10w,故考虑动态开线段树,每次只开根到这个节点上路径上经过的点,这样最多开log(N)*N即可,

    这样的话每次必须保存当前节点的左右儿子的id才可以准确访问左右儿子,其他和线段树差不多

    trick:注意开始要处理sum【0】,这样才可以保证当l==r时满足条件也能被统计上


    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn = 1e7 + 10;
    ll tree[maxn], lson[maxn], rson[maxn];
    ll tot;
    ll a[100005];
    ll sum[100005];
    const ll inf = 1e10;
    int n;
    ll root=1;
    
    int newnode()
    {
        ++tot;
        tree[tot] = lson[tot] = rson[tot] = 0;
        return tot;
    }
    
    void update(ll &x, ll l, ll r, ll val)
    {
        if(!x)
            x=newnode();
        tree[x]++;
        if(l == r)
            return;
        ll mid = (l+r)>>1;
        if(val<=mid ) update(lson[x], l, mid, val);
        else   update(rson[x], mid+1, r, val);
    }
    
    ll query(ll x, ll l, ll r, ll ql, ll qr)
    {
        if(ql<=l && qr>=r)
            return tree[x];
        ll mid = (l + r)>> 1;
        ll ans = 0;
        if(ql<=mid && lson[x]) ans +=query(lson[x], l , mid, ql, qr);
        if(qr>mid && rson[x]) ans+=query(rson[x], mid+1, r, ql, qr);
        return ans;
    }
    
    int main()
    {
        ll n, l ,r;
        scanf("%lld%lld%lld", &n, &l, &r);
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld", &a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        ll ans=0;
        update(root, -inf, inf, 0);
        for(int i = 1; i<=n;i++)
        {
            ans+=query(root, -inf, inf, sum[i]-r, sum[i]-l);
            update(root,-inf,inf,sum[i]);
        }
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
    要么优秀要么生锈
  • 相关阅读:
    datatime,time,string转换和format格式化处理
    迭代器和生成器进一步的认识
    对数据结构的新认识
    python StringIO中的 read()与 getvalue()
    git 分支策略
    js词法分析
    js作用域
    注解
    MapReduce过程详解(基于hadoop2.x架构)
    指数基金
  • 原文地址:https://www.cnblogs.com/Superwalker/p/7827942.html
Copyright © 2020-2023  润新知