hdu 3473 Minimum Sum(划分树-sum操作)

来源:互联网 发布:彩票11选5遗漏数据分析 编辑:程序博客网 时间:2024/05/28 15:16

           划分树。只是考虑求当前区间大于第k值的值得和,和小于第k值的和。显然可以在查询的时候直接搞出来。sum[d][i]表示第d层子区间l,r种l-i的和。写错了一个下标,检查了半辈子。。。

#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define MP make_pair#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;#define MID ((l+r)>>1)const int maxn = 100100;const int INF = 0x3f3f3f3f;struct KthNumber{    int a[maxn], s[maxn], t[20][maxn], num[20][maxn];    LL sum[20][maxn];    void init(int n)    {        for(int i = 1; i <= n; i ++)        {            scanf("%d", &a[i]);            s[i] = t[0][i] = a[i];        }        sort(s+1, s+n+1);    }    void Build(int d, int l, int r)    {        int lm = MID-l+1, lp = l, rp = MID+1;        for(int i = l; i <= MID; i ++)            lm -= s[i] < s[MID];        for(int i = l; i <= r; i ++)        {            if(i == l) num[d][i] = 0, sum[d][i] = 0;            else num[d][i] = num[d][i - 1], sum[d][i] = sum[d][i-1];            if(t[d][i] == s[MID])            {                if(lm)                {                    lm --; num[d][i] ++;                    t[d+1][lp++] = t[d][i];                }                else t[d+1][rp++] = t[d][i];            }            else if(t[d][i] < s[MID])            {                num[d][i] ++;                t[d+1][lp++] = t[d][i];            }            else t[d+1][rp++] = t[d][i];            sum[d][i] += t[d][i];        }        if(l<r)            Build(d+1, l, MID), Build(d+1, MID+1, r);    }    int Query(int d, int l, int r, int ql, int qr, int k)    {        if(l == r) return t[d][l];        int s, ss;        if(l == ql) s = 0, ss = num[d][qr];        else s = num[d][ql-1], ss = num[d][qr]-num[d][ql-1];        if(k <= ss) return Query(d+1, l, MID, l+s, l+s+ss-1, k);        else return Query(d+1, MID+1, r, MID+1+ql-l-s, MID+1+qr-l-s-ss, k-ss);    }    int val;    LL Query2(int d, int l, int r, int ql, int qr, int k)    {        if(l == r)        {            val = t[d][l];            return 0;        }        int s, ss;LL ret;        if(l == ql) s = 0, ss = num[d][qr];        else s = num[d][ql-1], ss = num[d][qr]-num[d][ql-1];        int l1 = l+s, r1 = l+s+ss-1, l2 = MID+1+ql-l-s, r2 = MID+1+qr-l-s-ss;        if(k <= ss)        {            ret = Query2(d+1, l, MID, l1, r1, k);            if(l2 <= r2) ret += sum[d+1][r2] - (l2 == MID+1 ? 0 : sum[d+1][l2 - 1]) - (r2-l2+1ll)*val;        }        else        {            ret = Query2(d+1, MID+1, r, l2, r2, k-ss);            if(l1 <= r1) ret += (r1-l1+1ll)*val - sum[d+1][r1] + (l1 == l ? 0 : sum[d+1][l1 - 1]);        }        return ret;    }}sol;int main(){    int n, m, T, cas = 1;    scanf("%d", &T);    while(T --)    {        scanf("%d", &n);        sol.init(n);        sol.Build(0, 1, n);        scanf("%d", &m);        printf("Case #%d:\n", cas ++);        while(m --)        {            int l, r, k;            scanf("%d%d", &l, &r);            l ++, r ++;k = (r-l+2)/2;            printf("%I64d\n", sol.Query2(0, 1, n, l, r, k));        }        puts("");    }}



2 0
原创粉丝点击