Bzoj4627:BeiJing2016-回转寿司

来源:互联网 发布:小学生数学软件 编辑:程序博客网 时间:2024/03/29 19:19

Description

酷爱日料的小Z经常光顾学校东门外的回转寿司店。在这里,一盘盘寿司通过传送带依次呈现在小Z眼前。不同的寿
司带给小Z的味觉感受是不一样的,我们定义小Z对每盘寿司都有一个满意度,例如小Z酷爱三文鱼,他对一盘三文
鱼寿司的满意度为10;小Z觉得金枪鱼没有什么味道,他对一盘金枪鱼寿司的满意度只有5;小Z最近看了电影“美
人鱼”,被里面的八爪鱼恶心到了,所以他对一盘八爪鱼刺身的满意度是-100。特别地,小Z是个著名的吃货,他
吃回转寿司有一个习惯,我们称之为“狂吃不止”。具体地讲,当他吃掉传送带上的一盘寿司后,他会毫不犹豫地
吃掉它后面的寿司,直到他不想再吃寿司了为止。今天,小Z再次来到了这家回转寿司店,N盘寿司将依次经过他的
面前,其中,小Z对第i盘寿司的满意度为Ai。小Z可以选择从哪盘寿司开始吃,也可以选择吃到哪盘寿司为止,他
想知道共有多少种不同的选择,使得他的满意度之和不低于L,且不高于R。注意,虽然这是回转寿司,但是我们不
认为这是一个环上的问题,而是一条线上的问题。即,小Z能吃到的是输入序列的一个连续子序列;最后一盘转走
之后,第一盘并不会再出现一次。

思路

考虑一个区间[l,r] 之和在[L..R]之间
假设我们已经知道了Pre[r],那么Pre[l1] 满足什么条件?

Pre[r]RPre[l1]Pre[r]L

是吧。
假如我们按顺序插入,以前缀和为下标插入树状数组(或者别的什么)
显然是不那么好的
考虑离散,以原数组在排序后的数组中的位置为下标
离散我用的二分(反正都排序了)
细节略繁琐(对我这样的蒟蒻来说)
其他的不再赘述了

代码

#include <cmath>#include <algorithm>using namespace std;typedef long long ll;char ch;bool fl;inline void read(int &a){    for(fl=0,ch=getchar();ch<'0'||ch>'9';ch=getchar()) fl^=(ch=='-');    for(a=0;ch>='0'&&ch<='9';ch=getchar())a=(a<<3)+(a<<1)+(ch^'0');    if(fl)a=-a;}const int N=1e5+10;int c[N];int n,i,d,l,r,L,R;ll Ans;inline void Ins(int i){ for(;i<=n+1;i+=i&(-i))c[i]++;}inline int Qry(int i){ int Ans=0;for(;i;i-=i&(-i))Ans+=c[i];return Ans;}struct Po{    ll v;    int id;    bool operator <(const Po &a)const{ return v<a.v;}}S[N],Pre[N];int GetL(int l,int r,ll V){    while(l<r){        int mid=(l+r)>>1;        if(S[mid].v>=V)r=mid;        else l=mid+1;    }    return l;}int GetR(int l,int r,ll V){    while(l<r){        int mid=((l+r)>>1)+1;        if(S[mid].v<=V)l=mid;        else r=mid-1;    }    return l;}int main(){    //freopen("a.in","r",stdin);    //freopen("a.out","w",stdout);    read(n);read(L);read(R);    for(i=1;i<=n;i++){        read(d);        Pre[i].v=Pre[i-1].v+d;    }    for(i=0;i<=n;i++)S[i].v=Pre[i].v,S[i].id=i;    sort(S,S+n+1);    for(i=0;i<=n;i++)Pre[S[i].id].id=i;    Ins(Pre[0].id+1);    for(i=1;i<=n;i++){        r=GetR(0,n,Pre[i].v-L);if(S[0].v>(Pre[i].v-L))r=-1;        l=GetL(0,n,Pre[i].v-R);if(S[n].v<(Pre[i].v-R))l=n+1;        if(l<=r) Ans+=Qry(r+1)-Qry(l);        Ins(Pre[i].id+1);    }    printf("%lld",Ans);    return 0;}
原创粉丝点击