您的位置:首页 > 其它

hdu 3473 Minimum Sum

2012-09-25 22:06 141 查看
题意:给你一个区间[l,r],要求sum(x-xi)(l<=i<=r)的最小值,其中x必须为xl,xl+1...xr中的一个数

当x为[l,r]的中位数的时候,满足要求。求任意区间的中位数可以用划分树(k-number)来解决,同样的,我们用suml[d][i]来记录划分树中第d层到数i位置放入左子树的数字的和,

具体见代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

#define MAXN 100010

long sorted[MAXN];
long toLeft[30][MAXN],val[30][MAXN];
__int64 lsum[30][MAXN],sum[MAXN];//lsum[d][i]为第d层到第xi被划入左子树的数字的和,sum[i]为1到i的和
__int64 lnum,rnum,suml,sumr,ans;

void build(int d,int l,int r)//建树
{
if(l==r)return;
int m = (l+r)>>1;
int i;
int same = m-l+1;//位于左子树的数据
for(i=l;i<=r;i++)  //计算放于左子树中与中位数相等的数字个数
if(val[d][i]<sorted[m])
same--;
int ls = l;
int rs = m+1;
for(i=l;i<=r;i++)
{
int flag = 0;
if((val[d][i]<sorted[m])||(val[d][i]==sorted[m]&&same>0))//放入左子树
{
flag = 1;
val[d+1][ls++] = val[d][i];
if(val[d][i]==sorted[m])same--;
lsum[d][i]=lsum[d][i-1]+val[d][i];
}
else//右子树
{
val[d+1][rs++] = val[d][i];
lsum[d][i]=lsum[d][i-1];
}
toLeft[d][i]=toLeft[d][i-1]+flag;
}
build(d+1,l,m);
build(d+1,m+1,r);
}
int query(int L,int R,int k,int d,int l,int r)
{
if(L==R)return val[d][L];
int m = (l+r)>>1;
int x = toLeft[d][L-1]-toLeft[d][l-1];//位于L左边的放于左子树中的数字个数
int y = toLeft[d][R] - toLeft[d][l-1];//到R为止位于左子树的个数
int ry = R-l-y;//到right右边为止位于右子树的数字个数
int cnt = y-x;//[left,right]区间内放到左子树中的个数
int rx = L-l-x;//left左边放在右子树中的数字个数
if(cnt>=k)
return query(l+x,l+y-1,k,d+1,l,m);
else
{
lnum=lnum+cnt;
suml=suml+lsum[d][R]-lsum[d][L-1];
return query(m+rx+1,m+1+ry,k-cnt,d+1,m+1,r);
}
}

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