zoukankan      html  css  js  c++  java
  • BZOJ4627 前缀和 + 权值线段树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4627

    题意:求序列中和在L到R之间的字串种数。

    要求的是和的范围,我们可以考虑先求一个前缀和pre,然后每个点j的贡献就是L <= pre[j] - pre[i] <= R(i < j)的i的种数了,移项一下变成

    pre[j] - R <= pre[i] <= pre[j] - L

    我们就可以考虑做个权值线段树维护一下所有pre,每次求贡献的时候做一个区间查询就可以了。

    注意点:

    1.由于范围太大又有负数,线段树要动态开点。

    2.开局要加一个pre[0] = 0的前缀和

    3.线段树里不必要开的点尽量不开否则可能由于空间WA

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
    while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
    const double eps = 1e-9;
    const int maxn = 1e5 + 10;
    const LL INF = 1e10 + 2e9;
    const int mod = 1e9 + 7; 
    int N,M,K;
    LL L,R;
    struct Tree{
        LL sum;
        int lt,rt;
        void init(){lt = rt = sum = 0;}
    }tree[maxn * 60];
    int tot;
    void check(int &t){
        if(t) return;
        t = ++tot;
        tree[t].init();
    }
    void Pushup(int &t){
        int ls = tree[t].lt,rs = tree[t].rt;
        tree[t].sum = tree[ls].sum + tree[rs].sum;
    }
    void update(int &t,LL l,LL r,LL x){
        check(t);
        if(l == r){
            tree[t].sum++;
            return;
        } 
        LL m = l + r >> 1;
        if(x <= m) update(tree[t].lt,l,m,x);
        else update(tree[t].rt,m + 1,r,x);
        Pushup(t);
    }
    LL query(int &t,LL l,LL r,LL ql,LL qr){
        if(!t) return 0;
        if(ql <= l && r <= qr) return tree[t].sum;
        LL m = l + r >> 1;
        if(qr <= m) return query(tree[t].lt,l,m,ql,qr);
        else if(ql > m) return query(tree[t].rt,m + 1,r,ql,qr);
        else return query(tree[t].lt,l,m,ql,m) + query(tree[t].rt,m + 1,r,m + 1,qr);
    }
    LL pre[maxn];
    int main(){
        N = read(); L = read(); R = read(); // sum[j] - L >= sum[i - 1] >= sum[j] - R;
        for(int i = 1; i <= N; i ++) pre[i] = read() + pre[i - 1];
        LL ans = 0;
        int root = 0;
        update(root,-INF,INF,0);
        for(int i = 1; i <= N ; i ++){
            if(pre[i] - R <= pre[i] - L) ans += query(root,-INF,INF,pre[i] - R,pre[i] - L);
            update(root,-INF,INF,pre[i]);
        }
        Prl(ans);
        return 0;
    }
  • 相关阅读:
    Magicodes.IE之花式导出
    Magicodes.IE之导入导出筛选器
    Magicodes.IE 2.3重磅发布——.NET Core开源导入导出库
    快速配置Azure DevOps代理服务器
    如何做好一个开源项目之徽章(二)
    使用Seq搭建免费的日志服务
    SpringBoot + SpringCloud Hystrix 实现服务熔断
    dedecms从word复制粘贴公式
    CuteEditor从word复制粘贴公式
    TinyMCE从word复制粘贴公式
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/10385872.html
Copyright © 2011-2022 走看看