HDU3473Minimum Sum

来源:互联网 发布:java jdk 1.7 for mac 编辑:程序博客网 时间:2024/05/20 22:40

//这题是利用划分树的题目;

//每层多加了一个变量lsum【dep】【i】表示该层放入左边的元素之和;

//之后在求中位数即第(b - a + 1) / 2大的数时,顺便利用lsum【dep】【i】求出中位数左边数之和,之后求出中位数右边数字之和;

//之后就显而易见了

#include<stdio.h>#include<algorithm>const int MAXN = 100100;int n, q, tcase;int order[MAXN], tree[25][MAXN], left[25][MAXN];__int64 lsum[25][MAXN], sum[MAXN], lsu;void Build(int x, int y, int dep){    if(x == y) return ;    int mid = (x + y) >> 1;    int lmid = mid - x + 1;    for(int i = x; i <= y; i++)        if(tree[dep][i] < order[mid])            lmid -- ;    int ls = x, rs = mid + 1;    __int64 ans = 0;    for(int i = x; i <= y; i++)    {        if(tree[dep][i] < order[mid])        {            tree[dep + 1][ls++] = tree[dep][i];            ans += tree[dep][i];        }        else if(tree[dep][i] > order[mid])        {            tree[dep + 1][rs++] = tree[dep][i];        }        else if(lmid > 0)        {            tree[dep + 1][ls++] = tree[dep][i];            ans += tree[dep][i];            lmid --;        }        else        {            tree[dep + 1][rs++] = tree[dep][i];        }        left[dep][i] = ls - x;        lsum[dep][i] = ans;//包括本身    }    Build(x, mid, dep + 1);    Build(mid + 1, y, dep + 1);}void Init(){    scanf("%d", &n);    sum[0] = 0;    for(int i = 1; i <= n; i++)    {        scanf("%d", &order[i]);        tree[0][i] = order[i];        sum[i] = sum[i-1] + order[i];    }    std::sort(order + 1, order + 1 + n);    Build(1, n, 0);}int Query(int x, int y, int dep, int l, int r, int k){    if(x == y)    {        lsu += tree[dep][x];        return tree[dep][x];    }    __int64 ls, lss;    int s, ss, mid = (x + y) >> 1; ;    if(l == x)    ss = 0, lss = 0;    else    ss = left[dep][l-1], lss = lsum[dep][l-1];        s = left[dep][r] - ss, ls = lsum[dep][r] - lss;    if(s >= k)        return  Query(x, mid , dep + 1, x + ss, x + left[dep][r] - 1, k);    else    {        lsu += ls;        return Query(mid + 1, y, dep + 1, mid + 1 + (l - x - ss), mid + 1 + (r - x - left[dep][r]), k - s);    }}void Solve(int cur){    int a, b, num, tmp;    __int64 ans;    scanf("%d", &q);    printf("Case #%d:\n", cur);    for(int i = 1; i <= q; i++)    {        scanf("%d%d", &a, &b);        num = b - a + 1;        lsu = 0;//中位数左边总和        tmp = Query(1, n, 0, a + 1, b + 1, (num + 1)/ 2);//中位数的值        ans = sum[b + 1] - sum[a] - lsu - lsu;        if(num & 1) ans += tmp;        printf("%I64d\n", ans);    }    putchar('\n');}int main(){    scanf("%d", &tcase);    for(int i = 1; i <= tcase; i++)    {        Init();        Solve(i);    }    return 0;}


原创粉丝点击