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 }
View Code

 

posted @ 2014-09-16 16:29  Mr.Youyu  阅读(117)  评论(0)    收藏  举报