Minimum Sum
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4775 Accepted Submission(s): 1083
Problem Description
You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you some intervals [l, r]. For each interval, you need to find a number x to make as small as possible!
Input
The first line is an integer T (T <= 10), indicating the number of test cases. For each test case, an integer N (1 <= N <= 100,000) comes first. Then comes N positive integers x (1 <= x <= 1,000, 000,000) in the next line. Finally, comes an integer Q (1 <= Q <= 100,000), indicting there are Q queries. Each query consists of two integers l, r (0 <= l <= r < N), meaning the interval you should deal with.
Output
For the k-th test case, first output “Case #k:” in a separate line. Then output Q lines, each line is the minimum value of . Output a blank line after every test case.
Sample Input
2 5 3 6 2 2 4 2 1 4 0 2 2 7 7 2 0 1 1 1
Sample Output
Case #1: 6 4 Case #2: 0 0
Author
standy
Source
2010 ACM-ICPC Multi-University Training Contest(4)——Host by UESTC
Recommend
zhengfeng | We have carefully selected several similar problems for you: 3474 1828 1698 1540 1394
解题思路: 区间内各个数与中位数的绝对值之和最小。
如果区间长度为偶数,则任取一个,如果为奇数则取中间的那个数作为中位数
由此得到一个公式就是区间比中位数小的数的个数lsum*中位数-区间中位数小的数的和+比中位数大的数的和-区间比中位数大
的个数*中位数
化简就是 rsum-lsum+mid*(lnum-rnum);
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 100005
int t[20][N],tl[20][N];
LL suml[20][N];
int sor[N];
LL sum[N];
LL lsum,lnum;
void build(int l,int r,int dep)
{
if(l==r)return ;
int m = (l+r)>>1;
int same = m-l+1;
for(int i=l;i<=r;i++)if(t[dep][i]<sor[m])same--;
//cout<<l<<" "<<r<<" "<<same<<endl;
int ln=l;
int rn=m+1;
for(int i=l;i<=r;i++)
{
if(t[dep][i]<sor[m]||(t[dep][i]==sor[m]&&same>0))
{
t[dep+1][ln++]=t[dep][i];
if(t[dep][i]==sor[m])same--;
tl[dep][i]=tl[dep][l-1]+ln-l;
suml[dep][i]=suml[dep][i-1]+t[dep][i];
}
else
{
t[dep+1][rn++]=t[dep][i];
tl[dep][i]=tl[dep][i-1];
suml[dep][i]=suml[dep][i-1];
}
}
build(l,m,dep+1);
build(m+1,r,dep+1);
}
int query(int l,int r,int ql,int qr,int k,int dep)
{
if(l==r)return t[dep][l];
int m=(l+r)>>1;
int cnt=tl[dep][qr]-tl[dep][ql-1];
if(cnt>=k)
{
int newl = l+tl[dep][ql-1]-tl[dep][l-1];
int newr = newl+cnt-1;
return query(l,m,newl,newr,k,dep+1);
}
else
{
int newr = qr+tl[dep][r]-tl[dep][qr];
int newl = newr-(qr-ql-cnt);
//cout<<ql<<" "<<qr<<endl;
lnum += cnt;
lsum += suml[dep][qr]-suml[dep][ql-1];
return query(m+1,r,newl,newr,k-cnt,dep+1);
}
}
int main()
{
int tt;
cin>>tt;
for(int cas=1;cas<=tt;cas++)
{
int n;
scanf("%d",&n);
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&t[0][i]);
sum[i]=t[0][i]+sum[i-1];
sor[i]=t[0][i];
}
sort(sor+1,sor+1+n);
build(1,n,0);
int m;
scanf("%d",&m);
printf("Case #%d:\n",cas);
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
l++,r++;
lsum=0,lnum=0;
int mid=query(1,n,l,r,(r-l)/2+1,0);
LL rsum = sum[r]-sum[l-1]-lsum-mid;
LL rnum = r-l-lnum;
LL ans = rsum - lsum+mid*1LL*(lnum-rnum);
//printf("mid=%d lnum=%lld rnum=%lld \n",mid,lnum,rnum);
printf("%lld\n",ans);
}
printf("\n");
}
}