直接套用划分树模板即可。
ACcode:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int NS=100010;
struct node{
LL sum[NS];
int num[NS];
int val[NS];
}row[18];
int n,m;
int st[NS];
LL sum[NS];
LL tot;
void build(int dep,int L,int R)
{
if (L==R) return ;
int mid=(L+R)>>1;
int same=mid-L+1;
int idl=L,idr=mid+1;
for (int i=L;i<=R;i++)
if (row[dep].val[i]<st[mid]) same--;
for (int i=L;i<=R;i++)
{
if (i==L) {
row[dep].sum[i]=0;
row[dep].num[i]=0;
} else {
row[dep].sum[i]=row[dep].sum[i-1];
row[dep].num[i]=row[dep].num[i-1];
}
if (row[dep].val[i]<st[mid]) {
row[dep].num[i]++;
row[dep].sum[i]+=row[dep].val[i];
row[dep+1].val[idl++]=row[dep].val[i];
} else if (row[dep].val[i]>st[mid]) {
row[dep+1].val[idr++]=row[dep].val[i];
} else {
if (same>0){
same--;
row[dep].num[i]++;
row[dep].sum[i]+=row[dep].val[i];
row[dep+1].val[idl++]=row[dep].val[i];
} else {
row[dep+1].val[idr++]=row[dep].val[i];
}
}
}
build(dep+1,L,mid);
build(dep+1,mid+1,R);
}
int query(int dep,int k,int x,int y,int L,int R)
{
if (L==R) return row[dep].val[L];
LL sxy;
int a,b,ctl,ctm;
int mid=(L+R)>>1;
if (x==L) {
ctl=0;
ctm=row[dep].num[y];
sxy=row[dep].sum[y];
} else {
ctl=row[dep].num[x-1];
ctm=row[dep].num[y]-ctl;
sxy=row[dep].sum[y]-row[dep].sum[x-1];
}
if (ctm>=k) {
a=L+ctl;
b=a+ctm-1;
R=mid;
} else {
a=mid+1+(x-L-ctl);
b=a+(y-x+1-ctm)-1;
tot+=sxy;
L=mid+1;
k-=ctm;
}
return query(dep+1,k,a,b,L,R);
}
int main()
{
int T,cas=1;
for (scanf("%d",&T);cas<=T;cas++)
{
scanf("%d",&n);
sum[0]=0;
memset(row,0,sizeof(row));
for (int i=1;i<=n;i++)
{
scanf("%d",&st[i]);
row[0].val[i]=st[i];
sum[i]=sum[i-1]+st[i];
}
sort(st+1,st+n+1);
build(0,1,n);
scanf("%d",&m);
printf("Case #%d:\n",cas);
while (m--)
{
int x,y,k;
scanf("%d %d",&x,&y),tot=0;
x++,y++,k=(y-x+2)>>1;
int nl=k-1,nr=y-x-k+2;
LL tmp=query(0,k,x,y,1,n);
LL suml=tot,sumr=sum[y]-sum[x-1]-tot;
suml=tmp*nl-suml,sumr=sumr-tmp*nr;
tmp=suml+sumr;
printf("%I64d\n",tmp);
}
puts("");
}
return 0;
}