hdu 3473 Minimum Sum(划分树)

题意:给你n个数,m个查询,对于每个查询,问在区间[a,b]内找到一个数x,使得最小。

同样是划分树,只是多记录了一个sum域,表示进入左子树的数的和。

如果不懂划分树:http://blog.csdn.net/shiqi_614/article/details/8041390

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MID(a,b) (a+((b-a)>>1))
typedef long long LL;
const int N=1e5+5;
struct P_Tree
{
    int order[N],n;
    int toLft[20][N],valu[20][N];
    LL sum[N],lsum[20][N],isum;
    void init(int len)
    {
        n=len;    sum[0]=0;
        for(int i=0;i<20;i++) lsum[i][0]=0,toLft[i][0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&order[i]);
            valu[0][i]=order[i];
            sum[i]=sum[i-1]+order[i];
        }
        sort(order+1,order+1+n);
        build(1,n,0);
    }
    void build(int lft,int rht,int ind)
    {
        if(lft==rht) return;
        int mid=MID(lft,rht);
        int same=mid-lft+1,ln=lft,rn=mid+1;
        for(int i=lft;i<=rht;i++)
            if(valu[ind][i]<order[mid]) same--;
        for(int i=lft;i<=rht;i++)
        {
            int flag=0;
            if((valu[ind][i]<order[mid])||valu[ind][i]==order[mid]&&same>0)
            {
                flag=1;
                valu[ind+1][ln++]=valu[ind][i];
                if(valu[ind][i]==order[mid]) same--;
                lsum[ind][i]=lsum[ind][i-1]+valu[ind][i];
            }
            else
            {
                lsum[ind][i]=lsum[ind][i-1];
                valu[ind+1][rn++]=valu[ind][i];
            }
            toLft[ind][i]=toLft[ind][i-1]+flag;
        }
        build(lft,mid,ind+1);
        build(mid+1,rht,ind+1);
    }
    int query(int st,int ed,int k,int lft,int rht,int ind)
    {
        if(lft==rht) return valu[ind][lft];
        int mid=MID(lft,rht);
        int lx=toLft[ind][st-1]-toLft[ind][lft-1];
        int ly=toLft[ind][ed]-toLft[ind][st-1];
        int rx=st-1-lft+1-lx;
        int ry=ed-st+1-ly;
        if(ly>=k) return query(lft+lx,lft+lx+ly-1,k,lft,mid,ind+1);
        else
        {
            isum+=lsum[ind][ed]-lsum[ind][st-1];
            st=mid+1+rx;
            ed=mid+1+rx+ry-1;
            return query(st,ed,k-ly,mid+1,rht,ind+1);
        }
    }
    LL solve(int a,int b,int k)
    {
        LL ele=query(a,b,k,1,n,0);
        LL res1=sum[b]-sum[a-1]-isum-ele-(b-a+1-k)*ele;
        LL res2=ele*(k-1)-isum;
        return res1+res2;
    }
}tree;
int main()
{
    int t,t_cnt=0;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,a,b,k;
        scanf("%d",&n);
        tree.init(n);
        scanf("%d",&m);
        printf("Case #%d:\n",++t_cnt);
        while(m--)
        {
            tree.isum=0;
            scanf("%d%d",&a,&b);
            a++;b++;
            k=(b-a+2)/2;
            LL res=tree.solve(a,b,k);
            printf("%I64d\n",res);
        }
        puts("");
    }
    return 0;
}


你可能感兴趣的:(struct,tree,query,Build)