您的位置:首页 > 其它

hdu 3473 Minimum Sum

2012-12-09 15:48 267 查看
题意:给出n个数x1,x2...xn.进行m次操作,每次给出一个区间[l ,r].求出xi属于区间[l, r]使得该区间的每个数与xi的差之和最小,并求出该和。

思路:划分树。

View Code

#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l,m,rt+1
#define rson m+1,r,rt+1
#define maxn 100001
struct node
{
int val[maxn];
int num[maxn];
__int64 sum[maxn];
}setree[18];
int sorted[maxn];
__int64 ans[maxn],sum;
void build(int l,int r,int rt)
{
if(l==r)
return ;
int m=(l+r)>>1;
int isame=m-l+1,same=0;
int ln=l,rn=m+1;
for(int i=l;i<=r;i++)
if(setree[rt].val[i]<sorted[m])
isame--;
for(int i=l;i<=r;i++){
if(i==l){
setree[rt].num[i]=0;
setree[rt].sum[i]=0;
}
else{
setree[rt].num[i]=setree[rt].num[i-1];
setree[rt].sum[i]=setree[rt].sum[i-1];
}
if(setree[rt].val[i]<sorted[m]){
setree[rt].num[i]++;
setree[rt].sum[i]+=setree[rt].val[i];
setree[rt+1].val[ln++]=setree[rt].val[i];
}
else if(setree[rt].val[i]>sorted[m])
setree[rt+1].val[rn++]=setree[rt].val[i];
else{
if(same<isame){
same++;
setree[rt].num[i]++;
setree[rt].sum[i]+=setree[rt].val[i];
setree[rt+1].val[ln++]=setree[rt].val[i];
}
else
setree[rt+1].val[rn++]=setree[rt].val[i];
}
}
build(lson);
build(rson);
}
__int64 query(int l,int r,int rt,int L,int R,int k)
{
if(L==R)
return setree[rt].val[L];
int m=(l+r)>>1;
int enterleft1,enterleft2,enterright1,enterright2;
__int64 ss;
if(L==l){
enterleft1=0;
enterleft2=setree[rt].num[R];
enterright1=0;
enterright2=R-l+1-setree[rt].num[R];
ss=setree[rt].sum[R];
}
else{
enterleft1=setree[rt].num[L-1];
enterleft2=setree[rt].num[R];
enterright1=L-l-setree[rt].num[L-1];
enterright2=R-l+1-setree[rt].num[R];
ss=setree[rt].sum[R]-setree[rt].sum[L-1];
}
int temp=enterleft2-enterleft1;
if(temp>=k)
return query(lson,l+enterleft1,l+enterleft2-1,k);
else{
sum+=ss;
return query(rson,m+enterright1+1,m+enterright2,k-temp);
}
}
int main()
{
int t;
scanf("%d",&t);
int cas=1;
while(t--){
int n,m;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&setree[0].val[i]);
sorted[i]=setree[0].val[i];
if(i==0)
ans[i]=setree[0].val[i];
else
ans[i]=ans[i-1]+setree[0].val[i];
}
sort(sorted,sorted+n);
build(0,n-1,0);
scanf("%d",&m);
printf("Case #%d:\n",cas++);
while(m--){
int l,r,k;
scanf("%d%d",&l,&r);
k=(r-l+2)/2;
sum=0;
__int64 temp=query(0,n-1,0,l,r,k);
__int64 sum1=ans[r]-ans[l-1]-sum;
printf("%I64d\n",sum1-sum-(r-l+2-k)*temp+(k-1)*temp);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: