码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4627: [BeiJing2016]回转寿司

时间:2016-07-11 19:05:59      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

权值线段树。

要求 L<=(s[i]-s[j])<=R  (i<j)。 的i和j的数量。

所以把前缀和s加入一棵权值线段树,每次询问满足条件的范围中的权值的个数。

权值线段树不能像普通线段树一样预处理,否则因为权值范围过大会爆掉。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long 
using namespace std;
const LL inf = 10000000000ll;
const int maxn = 100000 + 10;
const int maxm = 8000000 + 10;

struct segtree {
    LL l[maxm],r[maxm];
    int lc[maxm],rc[maxm];
    int v[maxm],vid;
    
    void change(int &x,LL L,LL R,LL p) {
        if(!x) {x=++vid;l[x]=L;r[x]=R;}
        v[x]++;
        if(L==R) return;
        LL mid=(L+R)>>1;
        if(p<=mid) change(lc[x],L,mid,p);
        else change(rc[x],mid+1,R,p);    
    }
    
    int ask(int x,LL L,LL R) {
        if(!x) return 0;
        if(r[x]<L || l[x]>R) return 0;
        if(L<=l[x]&&r[x]<=R) return v[x];
        return ask(lc[x],L,R)+ask(rc[x],L,R);
    }
        
}seg;

int root;
LL res=0,n,L,R;

int main() {
    LL s=0;
    scanf("%lld%lld%lld",&n,&L,&R);
    for(int i=1,x;i<=n;i++) {
        scanf("%d",&x);        
        seg.change(root,-inf,inf,s);
        s+=x;
        res+=seg.ask(root,max(-inf,s-R),min(inf,s-L));
    }
    printf("%lld\n",res);
    return 0;    
}

bzoj4627: [BeiJing2016]回转寿司

标签:

原文地址:http://www.cnblogs.com/invoid/p/5660913.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!