2014-09-30 19:42:51
思路:这题比一般的划分树多了个sum的标记,即:每层多维护一个sum[]数组,用来记录 i 及其之前被划入左子树的元素的和。对于一段给定的区间,用划分树求出它的中位数,另外在查询(query_ptree)操作中要用全局变量记录两个量:比中位数小的元素的和、比中位数小的元素个数。
1 /************************************************************************* 2 > File Name: 3473.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 28 Sep 2014 10:00:25 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <queue> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 #define lpos (pos << 1) 18 #define rpos (pos << 1|1) 19 #define getmid(l,r) (l + (r - l) / 2) 20 typedef long long ll; 21 const int INF = 1 << 29; 22 const int maxn = 100010; 23 24 int sorted[maxn]; 25 ll ans,pnum; 26 27 struct node{ 28 int val[maxn]; 29 int num[maxn]; 30 ll sum[maxn]; 31 }t[20]; 32 33 void Build_ptree(int p,int l,int r){ 34 if(l == r) return; 35 int mid = getmid(l,r); 36 int isame = mid - l + 1; 37 for(int i = l; i <= r; ++i) 38 if(t[p].val[i] < sorted[mid]) --isame; 39 int ls = l,rs = mid + 1; 40 for(int i = l; i <= r; ++i){ 41 t[p].num[i] = (i == l ? 0 : t[p].num[i - 1]); 42 t[p].sum[i] = (i == l ? 0 : t[p].sum[i - 1]); 43 if(t[p].val[i] < sorted[mid]){ 44 t[p].num[i]++; 45 t[p].sum[i] += t[p].val[i]; 46 t[p + 1].val[ls++] = t[p].val[i]; 47 } 48 else if(t[p].val[i] > sorted[mid]){ 49 t[p + 1].val[rs++] = t[p].val[i]; 50 } 51 else{ 52 if(isame){ 53 --isame; 54 t[p].num[i]++; 55 t[p].sum[i] += t[p].val[i]; 56 t[p + 1].val[ls++] = t[p].val[i]; 57 } 58 else t[p + 1].val[rs++] = t[p].val[i]; 59 } 60 } 61 Build_ptree(p + 1,l,mid); 62 Build_ptree(p + 1,mid + 1,r); 63 } 64 65 int Query_ptree(int a,int b,int k,int p,int l,int r){ 66 if(l == r) return t[p].val[a]; 67 int mid = getmid(l,r); 68 int ln,rn,preln,prern; 69 ll tsum; 70 ln = t[p].num[b] - (a == l ? 0 : t[p].num[a - 1]); 71 preln = (a == l ? 0 : t[p].num[a - 1]); 72 tsum = t[p].sum[b] - (a == l ? 0 : t[p].sum[a - 1]); 73 if(ln >= k){ 74 a = l + preln; 75 b = l + preln + ln - 1; 76 return Query_ptree(a,b,k,p + 1,l,mid); 77 } 78 else{ 79 prern = a - l - preln; 80 rn = b - a + 1 - ln; 81 a = mid + 1 + prern; 82 b = mid + prern + rn; 83 ans += tsum; 84 pnum += ln; 85 return Query_ptree(a,b,k - ln,p + 1,mid + 1,r); 86 } 87 } 88 89 int main(){ 90 ll sum[maxn]; 91 int T,n,q,a,b; 92 scanf("%d",&T); 93 for(int Case = 1; Case <= T; ++Case){ 94 scanf("%d",&n); 95 memset(t,0,sizeof(t)); 96 sum[0] = 0; 97 for(int i = 1; i <= n; ++i){ 98 scanf("%d",&sorted[i]); 99 t[1].val[i] = sorted[i]; 100 sum[i] = sum[i - 1] + sorted[i]; 101 } 102 sort(sorted + 1,sorted + n + 1); 103 Build_ptree(1,1,n); 104 scanf("%d",&q); 105 printf("Case #%d:\n",Case); 106 while(q--){ 107 scanf("%d%d",&a,&b); 108 ++a; 109 ++b; 110 ans = pnum = 0; 111 int k = (b - a + 2) / 2; 112 ll median = Query_ptree(a,b,k,1,1,n); 113 printf("%I64d\n",median * pnum - ans + sum[b] - sum[a - 1] - ans - (b - a + 1 - pnum) * median); 114 } 115 puts(""); 116 } 117 return 0; 118 }