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 }