题意:给您一个数列 然后再给你一区间 让你在这个区间里找一个数使区间里的所有数与这个数差的绝对值和最小 ,
思路:
毫无疑问 这个数就是中位数(==可以推出来的) 对于区间是基数个 和偶数个 其实都一样 因为最后都约去了 : 假如x是所求的值 这个区间内比x小的有left个 比x大的有right个 其中left个的和为sum1 right个和位sum2 则所求为sum2-sum1 对于基数个与偶数个的问题只有left与right区别了 如果是奇数个则left==right 否则 left-right=1
这就好说了 如果不相等 也就是与最终结果差个x 。 其中sum1和left可以在查找的时候累加起来 这就就解决了!!!
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; int num[100010],tree[20][100010],cont[20][100010]; __int64 sum[20][100010],f[100010]; int build(int floot,int L,int R) { int mid=(L+R)/2; int cc=mid-L+1; int lstar=L,rstar=mid+1,i; for(i=L;i<=mid;i++) { if(num[i]<num[mid]) cc--; } sum[floot][0]=0; for(i=L;i<=R;i++) { if(i==L) { cont[floot][i]=0; } else { cont[floot][i]=cont[floot][i-1]; } sum[floot][i]=sum[floot][i-1]; if(tree[floot][i]==num[mid]) { if(cc) { cc--; cont[floot][i]++; sum[floot][i]+=tree[floot][i]; tree[floot+1][lstar++]=tree[floot][i]; } else tree[floot+1][rstar++]=tree[floot][i]; } else if(tree[floot][i]<num[mid]) { cont[floot][i]++; sum[floot][i]+=tree[floot][i]; tree[floot+1][lstar++]=tree[floot][i]; } else { tree[floot+1][rstar++]=tree[floot][i]; } } if(L==R) return 0; build(floot+1,L,mid); build(floot+1,mid+1,R); return 0; } __int64 ss; int c; int find(int floot,int L,int R,int left,int right,int k) { if(L==R) return tree[floot][L]; int mid=(L+R)/2; int s1,s2; if(L==left) { s1=0; s2=cont[floot][right]; } else { s1=cont[floot][left-1]; s2=cont[floot][right]-s1; } if(k<=s2) { return find(floot+1,L,mid,L+s1,L+s1+s2-1,k); } else { c+=s2; ss+=sum[floot][right]-sum[floot][left-1]; return find(floot+1,mid+1,R,mid-L+1+left-s1,mid-L+1+right-s1-s2,k-s2); } } int main() { int n,m,i,j,T,d=1; scanf("%d",&T); while(T--) { scanf("%d",&n); f[0]=0; for(i=1;i<=n;i++) { scanf("%d",&num[i]); tree[1][i]=num[i]; f[i]=f[i-1]+num[i]; } sort(num+1,num+1+n); build(1,1,n); int Q,left,right,k; scanf("%d",&Q); printf("Case #%d:\n",d++); while(Q--) { scanf("%d%d",&left,&right); left++; right++; ss=c=0; k=(right-left+2)/2; int t=find(1,1,n,left,right,k); __int64 x=f[right]-f[left-1]; int p=right-left+1; //printf("%I64d\n",(__int64)t*(c-(right-left+1-c))+f[right]-f[left-1]-ss-ss); printf("%I64d\n",(x-ss-ss)+((__int64)t*(2*c-p))); } printf("\n"); } return 0; }