您的位置:首页 > 其它

HDU 3473 Minimum Sum

2013-04-01 11:25 218 查看
#include<cstdio>
#include<algorithm>
using namespace std;

typedef __int64 lld;
#define M 100005
#define md(x,y) (((x)+(y))>>1)

int sorted[M];

struct node{
int val[M];// val记录第k层当前位置的元素的值
int num[M];// num记录元素所在区间的当前位置之前进入左孩子的个数
lld sum[M];// sum记录比当前元素小的元素的和。当前值为mid,即是进入左区间的元素的和
}t[20];

void build(int lft,int rht,int p){
if(lft==rht)return ;
int i,mid=md(lft,rht);
int isame=mid-lft+1,same=0;
/* isame用来标记和中间值val_mid 相等的,且分到左孩子的数的个数。
LBoy-2
初始时,假定当前区间[lft,rht]有mid-lft+1个和val_mid 相等。 先踢掉比中间值小的,剩下的就是要插入到左边的*/
for(i=lft;i<=rht;i++)
if(t[p].val[i]<sorted[mid])
isame--;
int ln=lft,rn=mid+1;
for(i=lft;i<=rht;i++){
if(i==lft){
t[p].num[i]=0;
t[p].sum[i]=0;
}else{
t[p].num[i]=t[p].num[i-1];
t[p].sum[i]=t[p].sum[i-1];
}
if(t[p].val[i]<sorted[mid]){
t[p].num[i]++;
t[p].sum[i]+=t[p].val[i];
t[p+1].val[ln++]=t[p].val[i];
}else if(t[p].val[i]>sorted[mid]){
t[p+1].val[rn++]=t[p].val[i];
}else{
if(same<isame){
same++;
t[p].num[i]++;
t[p].sum[i]+=t[p].val[i];
t[p+1].val[ln++]=t[p].val[i];
}else{
t[p+1].val[rn++]=t[p].val[i];
}
}
}
build(lft,mid,p+1);
build(mid+1,rht,p+1);
}

lld sum;

/*
s 记录区间[a, b]中进入左孩子的元素的个数。
ss 记录区间[lft, a-1)中计入左孩子的元素的个数。
sss记录区间[a, b]中小于第k大元素的值的和。
bb 表示[lft, a-1]中分到右孩子的个数
b2 表示[a, b] 中分到右孩子的个数。

*/
int query(int a,int b,int k,int p,int lft,int rht){
if(lft==rht)return t[p].val[a];
int s,ss,b2,bb,mid=md(lft,rht);
lld sss;
if(a==lft){
s=t[p].num[b];
ss=0;
sss=t[p].sum[b];
}else{
s=t[p].num[b]-t[p].num[a-1];
ss=t[p].num[a-1];
sss=t[p].sum[b]-t[p].sum[a-1];
}

if(s>=k){
a=lft+ss;
b=lft+ss+s-1;
return query(a,b,k,p+1,lft,mid);
}else{
bb=a-lft-ss;
b2=b-a+1-s;
a=mid+bb+1;
b=mid+bb+b2;
sum+=sss;
return query(a,b,k-s,p+1,mid+1,rht);
}
}

lld tot[M];

int main(){
int T,Q,n;
int a,b;
int i,j;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&sorted[i]);
tot[i]=tot[i-1]+sorted[i];
t[0].val[i]=sorted[i];
}
sort(sorted+1,sorted+n+1);
build(1,n,0);
scanf("%d",&Q);
printf("Case #%d:\n",cas);
while(Q--){
scanf("%d%d",&a,&b);
a++;b++;
int k=(b-a+1)/2+1;
sum=0;
lld ret=query(a,b,k,0,1,n);
lld ans=ret*(k-1)-sum;
ans+=(tot[b]-tot[a-1]-sum)-ret*(b-a+2-k);
printf("%I64d\n",ans);
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: