zoj3606

  1 /*

  2 题意:售货员每隔w分钟就会睡觉,如果售货员睡着了那么顾客会叫醒她但是不会买东西,

  3 有n个客人会不同时间来,并且售货员卖给第i的客人的价格为p[i],并且售货员会在第k次卖

  4 出1+(k-1)%3个面包,求问最小的w使平均每次卖出的面包的价格最大即总收入/卖的次数;

  5 

  6 分析:如果w小于最小的时间间隔,那么售货员不会卖出一个面包显然不是最优的,

  7 当w>某一个时间间隔,那么会买面包的顾客都是时间间隔小于w的,

  8 显然最后答案肯定是某一个顾客的时间间隔,枚举要O(n^2),肯定超时;

  9 我们知道当w按顾客时间间隔递增,那么前面会买面包的顾客后面还是同样会买的,

 10 改变的只是卖的面包的个数,

 11 

 12 现在要完成的工作就是 单点更新,然后按照1,2,3,1,2,3的个数卖,求总收入和总买的次数

 13 

 14 我们可以通过线段树来完成这个工作,

 15 定义c[N<<2][3]和pos[N<<2];

 16 c[i][0]表示线段i起始位置顾客买1个面包,总的收入;

 17 c[i][1]表示线段i起始位置顾客买2个面包,总的收入;

 18 c[i][2]表示线段i起始位置顾客买3个面包,总的收入;

 19 pos[i]表示线段i里买面包的顾客的人数 

 20 

 21 这样就可以通过c[rt<<1][]和c[rt<<1|1][],来递推c[rt][];

 22 具体见代码;可以手推枚举一下;  

 23 trick:读入的时间不是按照顺序来的,要先排序,这个trick虽然很常见

 24 但是如果一不小心还是很容易掉进去不能自拔的;

 25  

 26 

 27 */

 28 #include<cstdio> 

 29 #include<cstring>

 30 #include<cstdlib>

 31 #include<iostream>

 32 #include<algorithm>

 33 #include<vector>

 34 #include<map>

 35 #define lson l,m,rt<<1

 36 #define rson m+1,r,rt<<1|1

 37 using namespace std;

 38 typedef long long LL;

 39 const int N=100000+10;

 40 const double eps=1e-10;

 41 LL c[N<<2][3];

 42 int pos[N<<2];

 43 vector<int> x,g[N];

 44 int n,n1;

 45 struct node{

 46     int pi,ti;

 47     bool operator < (const node&p)const{

 48         return ti<p.ti;

 49     }

 50 }nd[N];

 51 void init(){

 52     x.clear();

 53     for (int i=1;i<=n;i++){

 54         scanf("%d",&nd[i].pi);

 55     }    

 56     nd[0].ti=0;

 57     for (int  i=1;i<=n;i++){

 58         scanf("%d",&nd[i].ti);

 59     }

 60     sort(nd+1,nd+n+1);

 61     for (int i=1;i<=n;i++){

 62         x.push_back(nd[i].ti-nd[i-1].ti);

 63     }

 64     sort(x.begin(),x.end());

 65     n1=unique(x.begin(),x.end())-x.begin();

 66     for (int i=0;i<=n1;i++) g[i].clear();

 67     for (int i=1;i<=n;i++){

 68         int tmp=lower_bound(x.begin(),x.begin()+n1,nd[i].ti-nd[i-1].ti)-x.begin();

 69         g[tmp].push_back(i);

 70     }

 71     //cout<<"*** "<<endl;

 72     //for (int i=0;i<n1;i++) cout<<x[i]<<" ";cout<<endl;

 73 }

 74 void pushup(int rt){

 75     int t;

 76     pos[rt]=pos[rt<<1]+pos[rt<<1|1];

 77     t=pos[rt<<1]%3;

 78     for (int i=0;i<3;i++)

 79         c[rt][i]=c[rt<<1][i]+c[rt<<1|1][(t+i)%3];

 80     

 81 }

 82 void update(int L,int l,int r,int rt){

 83     if (l==r){

 84         c[rt][0]=nd[l].pi;

 85         c[rt][1]=nd[l].pi*2;

 86         c[rt][2]=nd[l].pi*3;

 87         pos[rt]=1;

 88         return;

 89     }

 90     int m=(l+r)>>1;

 91     if (L<=m) update(L,lson);

 92     else update(L,rson);

 93     pushup(rt);

 94 }

 95 void work(){

 96     LL ret1=0,ret2=0,ret3;

 97     memset(c,0,sizeof(c));

 98     memset(pos,0,sizeof(pos));

 99     for (int i=0;i<n1;i++){

100         int sz=g[i].size();

101         if (sz!=0){

102             for (int j=0;j<sz;j++){

103                 int v=g[i][j];

104                 update(v,1,n,1);

105             }

106             //double tmp=(double)c[1][0]/pos[1];

107         //    cout<<i<<" ** "<<c[1][0]<<" "<<pos[1]<<endl;

108             if (ret1==0 || c[1][0]*ret2>ret1*pos[1]) {

109                 ret1=c[1][0];

110                 ret2=pos[1];

111                 ret3=x[i];

112             }

113         }

114     }    

115     printf("%.6lf %.6lf\n",(double)ret3+eps,(double)ret1/ret2+eps);

116 }

117 int main(){

118     int T;scanf("%d",&T);

119     while (T--){

120         scanf("%d",&n);

121         init();

122         work();    

123     }

124     return 0;

125 }

 

你可能感兴趣的:(360)