Minimum Sum HDU - 3473

http://acm.hdu.edu.cn/showproblem.php?pid=3473

一开始用主席树 在MLE与TLE之间来回试探..

划分树存模板

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long

ll sum[20][100010];
ll pre[100010];
ll lsum,rsum;
int tree[20][100010];
int lef[20][100010];
int num[100010];
int n,q,lnum,rnum;

void build(int l,int r,int dep)
{
    int i,m,same,lpos,rpos;
    if(l==r)
    {
        sum[dep][l]=num[l];
        return;
    }
    m=(l+r)/2,same=m-l+1;
    for(i=l;i<=r;i++)
    {
        if(tree[dep][i]<num[m]) same--;
        sum[dep][i]=tree[dep][i];
        if(i>l) sum[dep][i]+=sum[dep][i-1];
    }
    lpos=l,rpos=m+1;
    for(i=l;i<=r;i++)
    {
        if(tree[dep][i]<num[m])
        {
            tree[dep+1][lpos++]=tree[dep][i];
            sum[dep][i]=sum[dep][i-1]+tree[dep][i];
        }
        else if(tree[dep][i]==num[m]&&same>0)
        {
            tree[dep+1][lpos++]=tree[dep][i];
            sum[dep][i]=sum[dep][i-1]+tree[dep][i];
            same--;
        }
        else
        {
            tree[dep+1][rpos++]=tree[dep][i];
            sum[dep][i]=sum[dep][i-1];
        }
        lef[dep][i]=lef[dep][l-1]+lpos-l;
    }
    build(l,m,dep+1);
    build(m+1,r,dep+1);
}

int query(int pl,int pr,int k,int l,int r,int dep)
{
    int cnt,m,newl,newr;
    if(pl==pr) return tree[dep][pl];
    cnt=lef[dep][pr]-lef[dep][pl-1],m=(l+r)/2;
    if(cnt>=k)
    {
        newl=l+lef[dep][pl-1]-lef[dep][l-1];
        newr=newl+cnt-1;
        return query(newl,newr,k,l,m,dep+1);
    }
    else
    {
        lnum+=cnt;
        lsum+=sum[dep][pr]-sum[dep][pl-1];
        newr=pr+lef[dep][r]-lef[dep][pr];
        newl=newr-(pr-pl-cnt);
        return query(newl,newr,k-cnt,m+1,r,dep+1);
    }
}

int main()
{
    ll ans;
    int t,cas,i,l,r,m;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i]);
            tree[0][i]=num[i];
            pre[i]=pre[i-1]+num[i];
        }
        sort(num+1,num+n+1);
        build(1,n,0);
        printf("Case #%d:\n",cas);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&l,&r);
            l++,r++;
            lnum=0,lsum=0;
            m=query(l,r,(r-l)/2+1,1,n,0);
            rnum=(r-l+1-lnum);
            rsum=(pre[r]-pre[l-1]-lsum);
            ans=rsum-lsum+m*(lnum-rnum);
            printf("%lld\n",ans);
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81134173