HDU 3473 Minimum Sum(划分树)

Minimum Sum

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2235    Accepted Submission(s): 512


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
 

 

Recommend
zhengfeng
 

 

 

 

 

 

其实就是找到中间那个数。

 

然后需要记录和,右边的减掉左边的

 

#include <stdio.h>

#include <algorithm>

#include <iostream>

#include <string.h>

using namespace std;

const int MAXN = 100010;

int tree[20][MAXN];

int sorted[MAXN];

int toleft[20][MAXN];

long long sum[20][MAXN];



void build(int l,int r,int dep)

{

    if(l == r)

    {

        sum[dep][l] = sum[dep][l-1]+tree[dep][l];

        return;

    }

    int mid = (l+r)>>1;

    int same = mid - l + 1;

    for(int i = l;i <= r;i++)

    {

        if(tree[dep][i] < sorted[mid])

            same--;

        sum[dep][i] += sum[dep][i-1]+tree[dep][i];

    }

    int lpos = l;

    int rpos = mid+1;

    for(int i = l;i <= r;i++)

    {

        if(tree[dep][i] < sorted[mid])

            tree[dep+1][lpos++] = tree[dep][i];

        else if(tree[dep][i] == sorted[mid] && same > 0)

        {

            tree[dep+1][lpos++] = tree[dep][i];

            same--;

        }

        else

            tree[dep+1][rpos++] = tree[dep][i];

        toleft[dep][i] = toleft[dep][l-1] + lpos - l;

    }

    build(l,mid,dep+1);

    build(mid+1,r,dep+1);

}

long long ans;

int query(int L,int R,int l,int r,int dep,int k)

{

    if(l == r)return tree[dep][l];

    int mid = (L+R)>>1;

    int cnt = toleft[dep][r] - toleft[dep][l-1];

    if(cnt >= k)

    {

        int ee = r-L+1-(toleft[dep][r]-toleft[dep][L-1])+mid;

        int ss = l-L-(toleft[dep][l-1]-toleft[dep][L-1])+mid;



        ans += sum[dep+1][ee]-sum[dep+1][ss];



        int newl = L + toleft[dep][l-1]-toleft[dep][L-1];

        int newr = newl + cnt -1;

        return query(L,mid,newl,newr,dep+1,k);

    }

    else

    {

        int s = L + toleft[dep][l-1] - toleft[dep][L-1];

        int e = s + cnt - 1;



        ans -= sum[dep+1][e] - sum[dep+1][s-1];



        int newr = r + toleft[dep][R] - toleft[dep][r];

        int newl = newr - (r-l+1-cnt) + 1;

        return query(mid+1,R,newl,newr,dep+1,k-cnt);

    }

}

int main()

{

    int T;

    int n;

    scanf("%d",&T);

    int iCase = 0;

    while(T--)

    {

        iCase++;

        scanf("%d",&n);

        memset(tree,0,sizeof(tree));

        memset(sum,0,sizeof(sum));

        for(int i = 1;i <= n;i++)

        {

            scanf("%d",&tree[0][i]);

            sorted[i] = tree[0][i];

        }

        sort(sorted+1,sorted+n+1);

        build(1,n,0);

        printf("Case #%d:\n",iCase);

        int m,l,r;

        scanf("%d",&m);

        while(m--)

        {

            scanf("%d%d",&l,&r);

            l++;r++;

            ans = 0;

            int tmp = query(1,n,l,r,0,(l+r)/2-l+1);

            if((l+r)%2)ans-=tmp;

            printf("%I64d\n",ans);

        }

        printf("\n");

    }

    return 0;

}

 

 

你可能感兴趣的:(HDU)