线段树
对于每个数字,分别处理更新
区间修改+等差数列
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e6+100;
typedef __int64 LL;
LL add[N<<2],st[N<<2],cha[N<<2];
#define ll o<<1
#define rr o<<1|1
#define mid (l+r)/2
void down(int l,int r,int o){
add[ll]+=add[o];
add[rr]+=add[o];
add[o]=0;
st[ll]+=st[o];cha[ll]+=cha[o];
st[rr]+=st[o]+(LL)(mid+1-l)*cha[o];cha[rr]+=cha[o];
st[o]=0,cha[o]=0;
}
int L,R;LL V,V1;int op;
void update(int l,int r,int o){
if(L<=l&&r<=R){
if(op==0){
add[o]+=V;
}
else {
st[o]+=V+(LL)(l-L)*V1;
cha[o]+=V1;
}
return ;
}
down(l,r,o);
if(L<=mid)update(l,mid,ll);
if(R>mid)update(mid+1,r,rr);
}
LL query(int l,int r,int o,int x){
if(l==r){
return add[o]+st[o];
}
down(l,r,o);
if(x<=mid)return query(l,mid,ll,x);
else return query(mid+1,r,rr,x);
}
int le[N],ri[N],aa[N];
int n;
void getlr(){
for(int i=1;i<=n;i++){
int j=i-1;
while(aa[j]>=aa[i]){
j=le[j];
}
le[i]=j;
}
for(int i=n;i>=1;i--){
int j=i+1;
while(aa[j]>aa[i]){
j=ri[j];
}
ri[i]=j;
}
}
void getup(){
memset(add,0,sizeof(add));
memset(st,0,sizeof(st));
memset(cha,0,sizeof(cha));
for(int i=1;i<=n;i++){
int x=i-(le[i]+1),y=(ri[i]-1)-i;
if(x>y)swap(x,y);
L=1,R=x+1,V=aa[i],V1=aa[i],op=1;
update(1,n,1);
L=x+2,R=x+1+y-x,V=(LL)(x+1)*aa[i],op=0;
if(L<=R)update(1,n,1);
L=x+1+y-x+1,R=x+1+y,V=(LL)x*aa[i],V1=-aa[i],op=1;
if(L<=R)update(1,n,1);
}
}
void pri(int xx[N],int n){
for(int i=1;i<=n;i++){
printf("%d%c",xx[i],i==n?'\n':' ');
}
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
scanf("%d",&aa[i]);
}
aa[0]=aa[n+1]=0;
getlr();
//pri(le,n);
//pri(ri,n);
getup();
int m;scanf("%d",&m);
for(int i=0;i<m;i++){
int a;scanf("%d",&a);
LL ans=query(1,n,1,a);
printf("%.10lf\n",(double)ans/(n-a+1));
}
}
return 0;
}