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; }
相关文章推荐
- HDU 3473-Minimum Sum(划分树-求区间sigma最小值)
- 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 (划分树)
- 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 (划分树求区间第k大带求和)(转)