hdu 3473
求Σ|x-xi| 最小,只要求得这个区间的中位数t,然后numl*t-suml+sumr-numr*t (如果是偶数个 任意取中间一个)。
求区间中位数,可以用划分树,suml 即区间内比中位数小的数的和,也可以同时求出来。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define MID ((l+r)>>1) 6 using namespace std; 7 typedef long long LL; 8 const int N = 100500; 9 10 int a[N],s[N],t[20][N],num[20][N],n,m; 11 LL sum[20][N]; 12 LL t1,t2; 13 void build(int c,int l,int r){ 14 int lm = MID - l + 1,lp = l,rp = MID + 1; 15 for(int i=l;i<=MID;i++) 16 lm-=s[i]<s[MID]; 17 for(int i = l ; i <= r; i++){ 18 if(i == l){ 19 num[c][i] = 0; 20 sum[c][i]=0; 21 } 22 else{ 23 num[c][i] = num[c][i-1]; 24 sum[c][i] = sum[c][i-1]; 25 } 26 if(t[c][i] == s[MID]){ 27 if(lm){ 28 lm--; 29 num[c][i]++; 30 sum[c][i]+=t[c][i]; 31 t[c+1][lp++] = t[c][i]; 32 }else 33 t[c+1][rp++] = t[c][i]; 34 } 35 else if( t[c][i] < s[MID]){ 36 num[c][i]++; 37 sum[c][i]+=t[c][i]; 38 t[c+1][lp++]=t[c][i]; 39 } 40 else 41 t[c+1][rp++]=t[c][i]; 42 } 43 if(l<r) 44 build(c+1,l,MID),build(c+1,MID+1,r); 45 } 46 47 int Query(int c,int l,int r,int ql,int qr,int k){ 48 LL L; 49 if(l == r){ 50 t1+=t[c][l]; 51 return t[c][l]; 52 } 53 int s,ss; 54 if(l == ql) 55 L=0,s=0,ss=num[c][qr]; 56 else 57 L=sum[c][ql-1],s=num[c][ql-1],ss=num[c][qr]-num[c][ql-1]; 58 if(k <= ss) 59 return Query(c+1,l,MID,l+s,l+s+ss-1,k); 60 else{ 61 t1+=sum[c][qr]-L; 62 return Query(c+1,MID + 1, r, MID+1+ql-l-s,MID+1+qr-l-s-ss,k-ss); 63 } 64 65 } 66 /*LL Query1(int c,int l,int r,int ql,int qr,int k){ 67 int s,ss; 68 LL L; 69 if(l == r){ 70 //t1+=t[c][l]; 71 return t[c][l]; 72 } 73 if(l == ql){ 74 s=0,ss=num[c][qr]; 75 L=0; 76 } 77 else{ 78 s=num[c][ql-1],ss=num[c][qr]-num[c][ql-1]; 79 L=sum[c][ql-1]; 80 } 81 if(k<=ss) 82 return Query1(c+1,l,MID,l+s,l+s+ss-1,k); 83 else 84 return sum[c][qr]-L+Query1(c+1,MID + 1, r, MID+1+ql-l-s,MID+1+qr-l-s-ss,k-ss); 85 }*/ 86 LL pre[N]; 87 int main() 88 { 89 int T; 90 int Q,l,r; 91 cin>>T; 92 for(int cas=1;cas<=T;cas++){ 93 scanf("%d",&n); 94 for(int i=1;i<=n;i++){ 95 scanf("%d",&a[i]); 96 s[i]=t[0][i]=a[i]; 97 } 98 sort(s+1,s+1+n); 99 build(0,1,n); 100 scanf("%d",&Q); 101 pre[0]=0; 102 for(int i=1;i<=n;i++){ 103 pre[i]=pre[i-1]+a[i]; 104 } 105 printf("Case #%d:\n",cas); 106 while(Q--){ 107 scanf("%d%d",&l,&r); 108 l++,r++; 109 t1=0; 110 LL t=Query(0,1,n,l,r,(r-l+2)>>1); 111 //t1=Query1(0,1,n,l,r,(r-l+2)>>1); 112 t2=pre[r]-pre[l-1]-t1; 113 int mid=(l+r)>>1; 114 printf("%I64d\n",t2-t1+(mid-l+1-(r-mid))*t); 115 } 116 printf("\n"); 117 } 118 return 0; 119 }

浙公网安备 33010602011771号