bzoj 4627: [BeiJing2016]回转寿司 线段树
2017-06-30 21:52
274 查看
题意
给一个序列,求有多少个子串满足其和在[L,R]范围内。n,|ai|<=100000,L,R<=1e9
分析
刷道水题找找手感。。。设s[i]表示前缀和。开一棵权值线段树,把整个序列扫一遍,每到一个数就把以这个数结尾对答案的贡献计算一下,然后把s[i]扔进线段树里面就好了。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int N=100005; const LL inf=1e10; int n,L,R,sz,root; LL a ; struct tree{int s,l,r;}t[N*30]; void ins(int &d,LL l,LL r,LL x) { if (!d) d=++sz; t[d].s++; if (l==r) return; LL mid=(l+r)/2; if (x<=mid) ins(t[d].l,l,mid,x); else ins(t[d].r,mid+1,r,x); } int find(int d,LL l,LL r,LL x,LL y) { if (x>y||!d) return 0; if (l==x&&r==y) return t[d].s; LL mid=(l+r)/2; return find(t[d].l,l,mid,x,min(y,mid))+find(t[d].r,mid+1,r,max(x,mid+1),y); } int main() { scanf("%d%d%d",&n,&L,&R); for (int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]+=a[i-1]; ins(root,0,inf*2,inf); LL ans=0; for (int i=1;i<=n;i++) { ans+=find(root,0,inf*2,max((LL)0,a[i]-R+inf),min(inf*2,a[i]-L+inf)); ins(root,0,inf*2,a[i]+inf); } printf("%lld",ans); return 0; }
相关文章推荐
- BZOJ 4627: [BeiJing2016]回转寿司【前缀和,值域线段树
- bzoj 4627: [BeiJing2016]回转寿司 -- 权值线段树
- bzoj-4627 [BeiJing2016]回转寿司 hash+权值线段树
- BZOJ 4627: [BeiJing2016]回转寿司 cdq
- BZOJ4627 回转寿司 值域线段树
- bzoj 4627: [BeiJing2016]回转寿司
- BZOJ4627 回转寿司(值域线段树)
- BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组
- 【BZOJ】4627 [BeiJing2016]回转寿司
- 【BZOJ4627】[BeiJing2016]回转寿司 SBT
- 4627: [BeiJing2016]回转寿司
- 【bzoj4627】[BeiJing2016]回转寿司 离散化+树状数组
- 值域线段树 bzoj 4627
- bzoj 4627 值域线段树
- 值域线段树 bzoj 4627
- 线段树套treap+dp(BZOJ1926)
- bzoj 1095 捉迷藏(线段树)
- [BZOJ 1012] JSOI 2008 最大数maxnumber · 线段树
- BZOJ 3073: [Pa2011]Journeys 线段树优化最短路
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】