找区间某个值减其他值的最小和,先找区间的中位数,再遍历区间求
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
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include<stdlib.h>
#include<cmath>
#include<map>
using namespace std;
typedef long long int LL;
const LL MAXL(1e5);
LL tree[20][MAXL+50];
LL toLeft[20][MAXL+50];
LL sorted[MAXL+50];
void Build_tree(LL level,LL left,LL right)
{
if(left==right)
return ;
LL mid=(left+right)>>1;
LL suppose=mid-left+1;
for(LL i=left;i<=right;i++)
if(tree[level][i]<sorted[mid])
suppose--;
LL subLeft=left,subRight=mid+1;
for(LL i=left;i<=right;i++)
{
if(i==left)
toLeft[level][i]=0;
else
toLeft[level][i]=toLeft[level][i-1];
if(tree[level][i]<sorted[mid]||tree[level][i]==sorted[mid]&&suppose>0)
{
tree[level+1][subLeft++]=tree[level][i];
toLeft[level][i]++;
if(tree[level][i]==sorted[mid])
suppose--;
}
else
tree[level+1][subRight++]=tree[level][i];
}
Build_tree(level+1,left,mid);
Build_tree(level+1,mid+1,right);
}
LL Query(LL level,LL qLeft,LL qRight,LL left,LL right,LL k)
{
LL mid=(left+right)>>1;
if(qLeft==qRight)
return tree[level][qLeft];
LL lef;
LL qlef;
if(qLeft==left)
lef=0,qlef=toLeft[level][qRight];
else
lef=toLeft[level][qLeft-1],qlef=toLeft[level][qRight]-lef;
if(k<=qlef)
{
LL newleft=left+lef;
LL newright=left+lef+qlef-1;
return Query(level+1,newleft,newright,left,mid,k);
}
else
{
LL newleft=mid+qLeft-left-lef+1;
LL newright=mid+qRight-left-qlef-lef+1;
return Query(level+1,newleft,newright,mid+1,right,k-qlef);
}
}
int main()
{
LL n,m,ans,k=0,t,s[MAXL+50];
scanf("%lld",&t);
while(t--)
{
k++;
scanf("%lld",&n);
for(LL i=0; i<n; i++)
{
scanf("%lld",&tree[0][i]);
sorted[i]=tree[0][i];
}
sort(sorted,sorted+n);
Build_tree(0,0,n-1);
memset(s,0,sizeof(s));
scanf("%lld",&m);
for(LL i=0;i<m;i++)
{
LL ql,qr;
scanf("%lld%lld",&ql,&qr);
LL d=(qr-ql+2)>>1;
ans=Query(0,ql,qr,0,n-1,d);
for(LL j=ql;j<=qr;j++)
s[i]+=max(ans-tree[0][j],tree[0][j]-ans);
}
printf("Case #%lld:\n",k);
for(LL i=0;i<m;i++)
printf("%lld\n",s[i]);
printf("\n");
}
return 0;
}