题意:给出n个数x1,x2...xn.进行m次操作,每次给出一个区间[l ,r].求出xi属于区间[l, r]使得该区间的每个数与xi的差之和最小,并求出该和。

思路:划分树。

View Code
  1 #include <cstdio>
  2 #include <algorithm>
  3 using namespace std;
  4 #define lson l,m,rt+1
  5 #define rson m+1,r,rt+1
  6 #define maxn 100001
  7 struct node
  8 {
  9     int val[maxn];
 10     int num[maxn];
 11     __int64 sum[maxn];
 12 }setree[18];
 13 int sorted[maxn];
 14 __int64 ans[maxn],sum;
 15 void build(int l,int r,int rt)
 16 {
 17     if(l==r)
 18     return ;
 19     int m=(l+r)>>1;
 20     int isame=m-l+1,same=0;
 21     int ln=l,rn=m+1;
 22     for(int i=l;i<=r;i++)
 23     if(setree[rt].val[i]<sorted[m])
 24     isame--;
 25     for(int i=l;i<=r;i++){
 26         if(i==l){
 27         setree[rt].num[i]=0;
 28         setree[rt].sum[i]=0;
 29         }
 30         else{
 31         setree[rt].num[i]=setree[rt].num[i-1];
 32         setree[rt].sum[i]=setree[rt].sum[i-1];
 33         }
 34         if(setree[rt].val[i]<sorted[m]){
 35             setree[rt].num[i]++;
 36             setree[rt].sum[i]+=setree[rt].val[i];
 37             setree[rt+1].val[ln++]=setree[rt].val[i];
 38         }
 39         else if(setree[rt].val[i]>sorted[m])
 40             setree[rt+1].val[rn++]=setree[rt].val[i];
 41         else{
 42             if(same<isame){
 43                 same++;
 44                 setree[rt].num[i]++;
 45                 setree[rt].sum[i]+=setree[rt].val[i];
 46                 setree[rt+1].val[ln++]=setree[rt].val[i];
 47             }
 48             else
 49                 setree[rt+1].val[rn++]=setree[rt].val[i];
 50         }    
 51     }
 52     build(lson);
 53     build(rson);
 54 }
 55 __int64 query(int l,int r,int rt,int L,int R,int k)
 56 {
 57     if(L==R)
 58     return setree[rt].val[L];
 59     int m=(l+r)>>1;
 60     int enterleft1,enterleft2,enterright1,enterright2;
 61     __int64 ss;
 62     if(L==l){
 63         enterleft1=0;
 64         enterleft2=setree[rt].num[R];
 65         enterright1=0;
 66         enterright2=R-l+1-setree[rt].num[R];
 67         ss=setree[rt].sum[R];
 68     }
 69     else{
 70         enterleft1=setree[rt].num[L-1];
 71         enterleft2=setree[rt].num[R];
 72         enterright1=L-l-setree[rt].num[L-1];
 73         enterright2=R-l+1-setree[rt].num[R];
 74         ss=setree[rt].sum[R]-setree[rt].sum[L-1];
 75     }
 76     int temp=enterleft2-enterleft1;
 77     if(temp>=k)
 78     return query(lson,l+enterleft1,l+enterleft2-1,k);
 79     else{
 80         sum+=ss;
 81     return query(rson,m+enterright1+1,m+enterright2,k-temp);
 82     }
 83 }
 84 int main()
 85 {
 86     int t;
 87     scanf("%d",&t);
 88     int cas=1;
 89     while(t--){
 90         int n,m;
 91         scanf("%d",&n);
 92         for(int i=0;i<n;i++){
 93             scanf("%d",&setree[0].val[i]);
 94             sorted[i]=setree[0].val[i];
 95             if(i==0)
 96             ans[i]=setree[0].val[i];
 97             else
 98             ans[i]=ans[i-1]+setree[0].val[i];
 99         }
100         sort(sorted,sorted+n);
101         build(0,n-1,0);
102         scanf("%d",&m);
103         printf("Case #%d:\n",cas++);
104         while(m--){
105             int l,r,k;
106             scanf("%d%d",&l,&r);
107             k=(r-l+2)/2;
108             sum=0;
109             __int64 temp=query(0,n-1,0,l,r,k);
110             __int64 sum1=ans[r]-ans[l-1]-sum;
111             printf("%I64d\n",sum1-sum-(r-l+2-k)*temp+(k-1)*temp);
112         }
113         printf("\n");
114     }
115     return 0;
116 }