zoukankan      html  css  js  c++  java
  • 值域线段树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
    要么优秀要么生锈
  • 相关阅读:
    log4net 简单使用教程(配置)
    C#WinForm 国际化的简单实现,多语言实现
    EF Power Tool 参数错误 HRESULT:0x80070057 (E_INVALIDARG)) 解决办法
    如何用委托与事件实现winfrom窗体之间值传递
    VS2010自带的Dotfuscator 5注册
    WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放
    POJ_3211 Washing Clothes (01背包)
    POJ_3624 Charm Bracelet ( 01背包 )
    集训队内部测试赛(2012.01.02)
    HDU_1011 Starship Troopers && HDU_1561 The more, The Better (树型dp)
  • 原文地址:https://www.cnblogs.com/Superwalker/p/7827942.html
Copyright © 2011-2022 走看看