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位置放入左子树的数字的和,
具体见代码:
当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; }
相关文章推荐
- HDU 3473 Minimum Sum(划分树)
- HDU 3473 Minimum Sum (划分树)
- hdu 3473 Minimum Sum 划分树
- hdu 3473 Minimum Sum
- HDU 3473 Minimum Sum
- hdu 3473 Minimum Sum
- HDU 3473 Minimum Sum (划分树求区间第k大带求和)(转)
- HDU 3473 Minimum Sum 划分树,数据结构 难度:1
- HDU 3473 Minimum Sum(划分树,求中位数,小于中位数的和与大于中位数的和)
- HDU 3473 Minimum Sum
- HDU 3473 Minimum Sum (划分树)
- hdu 3473 Minimum Sum(划分树应用)
- 【划分树】 HDU 3473 Minimum Sum 中位数
- HDU 3473 Minimum Sum
- HDU 3473 Minimum Sum (划分树)
- hdu 3473 Minimum Sum 划分树的应用
- hdu 3473 Minimum Sum(划分树)
- hdu 3473 Minimum Sum(划分树-sum操作)
- HDU 3473 Minimum Sum 划分树
- Minimum Sum - HDU 3473 划分树