• P5459 [BJOI2016]回转寿司


    传送门

    暴力怎么搞,维护前缀和 $s[i]$ ,对于每一个 $s[i]$,枚举所有 $jin[0,i-1]$,看看 $s[i]-s[j]$ 是否属于 $[L,R]$

    如果属于就加入答案

    $s[i]-s[j]in[L,R]$ 等价于 $s[i]-s[j] geqslant L , s[i]-s[j] leqslant R$

    即 $s[i]-L geqslant s[j] , s[i]-R leqslant s[j]$

    发现对于每一个 $i$ 其实就是问区间 $[0,i-1]$ 中权值在 $[s[i]-L,s[i]-R]$ 之间的 $s[j]$ 的数量

    直接权值树状数组,发现值域太大,所以要离散化

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e6+7;
    int n,L,R;
    int t[N];
    ll ans,a[N],s[N];//注意long long
    inline void add(int x) { while(x<=n+1) t[x]++,x+=x&-x; }
    inline int ask(int x) { int res=0; while(x) res+=t[x],x-=x&-x; return res; }
    int main()
    {
        n=read(),L=read(),R=read();
        for(int i=1;i<=n;i++) a[i]=s[i]=s[i-1]+read();
        sort(a+1,a+n+2);
        for(int i=0;i<=n;i++)//注意i=0
        {
            int tr=lower_bound(a+1,a+n+2,s[i]-L+1)-a-1;//这个等价于upper_bound(a+1,a+n+2,s[i]-L)-a-1;
            int tl=lower_bound(a+1,a+n+2,s[i]-R)-a;
            ans+=ask(tr)-ask(tl-1);
            add(lower_bound(a+1,a+n+2,s[i])-a);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    //si-sj>=L  si-L>=sj sj<=si-L
    //si-sj<=R  si-R<=sj sj>=si-R
  • 相关阅读:
    【转】QT创建子对话框的方法
    IplImage转为Mat的方法
    浅谈Android选项卡(二)
    浅谈Android选项卡(一)
    Android来电、去电监听
    文件加密
    Java实现文件重命名
    使用单个httpclient实例请求数据。
    获取Android状态栏的高度
    [置顶] 微软翻译接口
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11175354.html
Copyright © 2020-2023  润新知