BZOJ 4627: [BeiJing2016]回转寿司【前缀和,值域线段树

来源:互联网 发布:node.js跟java哪个好学 编辑:程序博客网 时间:2024/04/28 18:28

就是求 区间和∈[L,R]的区间的个数

求一下前缀和,就是对于每个右端点查询左边 前缀和∈[sum[i]-R , sum[i]-L]的个数

值域线段树瞎搞搞就好

注意值可能为负

还要先插入一个0表示sum[0] = 0 【感谢良心样例

#include<bits/stdc++.h>#define MAXN 100005#define INF 10000000000llusing namespace std;int n;long long ll,rr;long long sum[MAXN];struct t1{int cnt,leftson,rightson;}dt[MAXN * 85];int cnt_node = 1 , root = 1;void insert(int &now,long long l,long long r,long long v){if(!now)now = ++cnt_node;++dt[now].cnt;if(l==r)return ;long long mid = (l+r)>>1;if(v<=mid)insert(dt[now].leftson,l,mid,v);elseinsert(dt[now].rightson,mid+1,r,v);}int inqry(int now,long long l,long long r,long long L,long long R){if(L<=l&&r<=R)return dt[now].cnt;long long mid = (l+r)>>1;int tmp = 0;if(L<=mid && dt[now].leftson)tmp = inqry(dt[now].leftson,l,mid,L,R);if(mid<R && dt[now].rightson)tmp += inqry(dt[now].rightson,mid+1,r,L,R);return tmp;}int main(){//freopen("1.in","r",stdin);scanf("%d%lld%lld",&n,&ll,&rr);for(int i=1;i<=n;++i)scanf("%lld",sum+i),sum[i] += sum[i-1];long long ans = 0;insert(root,-INF,INF,0);for(int i=1;i<=n;++i){ans += inqry(root,-INF,INF,sum[i]-rr,sum[i]-ll);insert(root,-INF,INF,sum[i]);}printf("%lld",ans);return 0;}


0 0
原创粉丝点击