/*
分析:
划分树,赶脚是水题,但是中间莫名其妙的爆int64了,
检查了俩小时囧~~~
在划分树里面加入信息sum代表划分到左子树的数的和就
行了。唯一的安慰是,这做的第一道要加入sum信息的划分树
思路和代码全是自己的囧~~~
2013-04-01
*/
#include"iostream"
#include"cstdio"
#include"cstring"
#include"algorithm"
using namespace std;
const int N=20;
const int M=100111;
int n,m;
__int64 sum[N][M],SUM[M];
int tr[N][M],toleft[N][M],sorted[M];
void build(int l,int r,int k)
{
if(l==r) return ;
int i,mid,equ,ln,rn;
mid=(l+r)>>1;equ=0;ln=l;rn=mid+1;
for(i=mid;i>=l;i--)
{
if(sorted[i]==sorted[mid]) equ++;
else break;
}
for(i=l;i<=r;i++)
{
sum[k][i]=sum[k][i-1];
toleft[k][i]=toleft[k][i-1];
if(tr[k][i]<sorted[mid])
{
tr[k+1][ln++]=tr[k][i];
toleft[k][i]++;
sum[k][i]+=tr[k][i];
}
else if(tr[k][i]==sorted[mid])
{
if(equ)
{
tr[k+1][ln++]=tr[k][i];
equ--;
toleft[k][i]++;
sum[k][i]+=tr[k][i];
}
else tr[k+1][rn++]=tr[k][i];
}
else tr[k+1][rn++]=tr[k][i];
}
build(l,mid,k+1);
build(mid+1,r,k+1);
}
int numl,numr;
__int64 suml,sumr;
int query(int a,int b,int aim,int l,int r,int k)
{
if(l==r) return tr[k][l];
/*numl统计的是“小于”区间第aim大的数的数量①,如果要统计“小于等于”第aim
大的数②,这儿要上面这行要写成这个:
if(l==r)
{
suml+=tr[k][l];
numl++;
return tr[k][l];
}
而这个题,①、②都对,因为中间的数被消掉了*/
int mid,p,pp;
mid=(l+r)>>1;
p=toleft[k][a-1]-toleft[k][l-1];
pp=toleft[k][b]-toleft[k][a-1];
if(pp>=aim) return query(l+p,l+p+pp-1,aim,l,mid,k+1);
else
{
int z,zz;
z=a-l-p;
zz=b-a+1-pp;
numl+=pp;
suml+=sum[k][b]-sum[k][a-1];
return query(mid+z+1,mid+z+zz,aim-pp,mid+1,r,k+1);
}
}
int main()
{
int T,Case;
int i;
int a,b,temp;
__int64 ave,ans;
cin>>T;
for(Case=1;Case<=T;Case++)
{
SUM[0]=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&tr[0][i]);
sorted[i]=tr[0][i];
SUM[i]=SUM[i-1]+tr[0][i];
}
for(i=0;i<20;i++) sum[i][0]=toleft[i][0]=0;
sort(sorted+1,sorted+n+1);
build(1,n,0);
scanf("%d",&m);
printf("Case #%d:\n",Case);
while(m--)
{
scanf("%d%d",&a,&b);
a++;b++;
temp=(b-a)/2+1;
suml=numl=0;
ave=query(a,b,temp,1,n,0);
numr=b-a+1-numl;
sumr=SUM[b]-SUM[a-1]-suml;
ans=numl*ave-suml+sumr-numr*ave;
printf("%I64d\n",ans);
}
printf("\n");
}
return 0;
}