zoj zju 3606 Lazy Salesgirl

来源:互联网 发布:java 轮询查询数据库 编辑:程序博客网 时间:2024/06/04 18:41

题意:有一个售货员,n个顾客,卖给 i 这个顾客的价格是pi,i 顾客来买东西的时刻为 ti

如果有w的时间段没人来买东西,售货员就会睡着,下一个顾客来时会叫醒她,但是不买东西

售货员会卖给第i个来(相对顺序)的顾客 1 + ((i - 1) mod 3)的数量的面包 即 1 2 3 中的一个

问使得平均的销售额最大的最小w以及此时的平均销售额是多少( 总的销售额/顾客的个数)

 

做法:我觉得关键是要抓住题目的特点,深挖下去,售货员每隔w时间会睡着,那就意味着,

1:如果有个顾客和上一个顾客间的时间间隔超过了w,这个顾客就不糊买东西,而与上一个顾客来的时间间隔小于等于w的顾客肯定能买到面包

所以我们只需枚举每个时间间隔既可,答案肯定就是某个时间间隔,一旦时间间隔定了,那能卖的面包数以及买到东西的顾客数也就定了

2:买到面包的数量问题,由题目给出的式子可得,卖出面包数量的序列 为1 2 3 1 2 3.。。。所以如果知道了某个人买了几个面包,那么可以

推算出接下来第x个人买了几个面包,因为最多也只有三种情况,所以把三种情况的结果都保存一下,就用到了三个线段树,其实就是线段树的域开个二维数组

线段树的域:

sum[rt]:记录当前节点的区间内共有几个顾客

pp[rt][3]:记录当区间最左边的人分别买了 1 2 3个面包时总的销售额

那么我们可以通过线段树将这个结果传递上去

关键代码:

for(int i=0;i<3;i++)
        pp[x][i]=pp[x<<1][i]+pp[x<<1|1][(sum[x<<1]+i)%3];

知道了左子树第一个人买的面包个数,和左子树的人数,自然就可以推出右子树第一个人买的面包个数,三种情况都记录一下,然后再传递上去

最后的结果是pp[1][0],因为第一个人肯定只买了一个面包;

View Code
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,x<<1#define rson m+1,r,x<<1|1const int maxn = 100010;int sum[maxn<<2];double pp[maxn<<2][3];struct node{    int id,len,num,tt;    bool operator < (const node &cmp) const{        return tt<cmp.tt;    }}a[maxn],cnt[maxn];void update(int pos,int l,int r,int x){    sum[x]++;    if(l==r){        for(int i=0;i<3;i++)  pp[x][i]=1.0*(i+1)*a[pos].num;        return ;    }    int m=(l+r)>>1;    if(pos<=m) update(pos,lson);    else update(pos,rson);    for(int i=0;i<3;i++)        pp[x][i]=pp[x<<1][i]+pp[x<<1|1][(sum[x<<1]+i)%3];}int main(){    int t,n,i,j;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        for(i=1;i<=n;i++)  scanf("%d",&a[i].num);        for(i=1;i<=n;i++)  scanf("%d",&a[i].tt);        sort(a+1,a+n+1);        a[0].tt=0;        for(i=1;i<=n;i++) {            cnt[i].tt=a[i].tt-a[i-1].tt;            cnt[i].id=i;        }        memset(sum,0,sizeof(sum));        memset(pp,0,sizeof(pp));        sort(cnt+1,cnt+n+1);        double aver_ans=0,w_ans;        for(i=1,j=1;i<=n;i=j){            while(cnt[j].tt==cnt[i].tt && j<=n) //j<=n                 update(cnt[j].id,1,n,1);                j++;            }            double tmp=pp[1][0]*1.0/sum[1];            if(tmp>aver_ans){                aver_ans=tmp;                w_ans=cnt[i].tt;            }        }         printf("%.6lf %.6lf\n",w_ans,aver_ans);    }    return 0;}
原创粉丝点击