Minimum Sum

找区间某个值减其他值的最小和,先找区间的中位数,再遍历区间求

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;
}

猜你喜欢

转载自blog.csdn.net/jk211766/article/details/81544328
今日推荐