题意:给出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 }