HDU 3473 Minimum Sum 划分树,数据结构 难度:1

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

划分树模板题目,需要注意的是划分树的k是由1开始的

划分树:

参考:http://blog.csdn.net/shiqi_614/article/details/8041390

划分树的定义

 

         划分树定义为,它的每一个节点保存区间[lft,rht]所有元素,元素顺序与原数组(输入)相同,但是,两个子树的元素为该节点所有元素排序后(rht-lft+1)/2个进入左子树,其余的到右子树,同时维护一个num域,num[i]表示lft->i这个点有多少个进入了左子树。

 

划分树的Sample

 HDU 3473 Minimum Sum 划分树,数据结构 难度:1

 

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

typedef long long ll;

const int maxn=1e5+5;

const int maxf=20;

int order[maxn];

int v[maxf][maxn];

ll s[maxn];

ll sum[maxf][maxn],asum;

int num[maxf][maxn];

void build(int l,int r,int ind){

        if(l==r)return ;

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

        int ln=l,rn=mid+1,same=mid-l+1;

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

                if(v[ind][i]<order[mid])same--;

        }

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

                int flag=0;

                if(v[ind][i]==order[mid]&&same>0){

                        same--;

                        flag=1;

                        v[ind+1][ln++]=v[ind][i];

                        sum[ind][i]=(i>0?sum[ind][i-1]:0)+v[ind][i];

                }

                else if(v[ind][i]<order[mid]){

                        flag=1;

                        v[ind+1][ln++]=v[ind][i];

                        sum[ind][i]=(i>0?sum[ind][i-1]:0)+v[ind][i];

                }

                else {

                        sum[ind][i]=i>0?sum[ind][i-1]:0;

                        v[ind+1][rn++]=v[ind][i];

                }

                num[ind][i]=(i>0?num[ind][i-1]:0)+flag;

        }

        build(l,mid,ind+1);

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

}

int query(int s,int e,int k,int l,int r,int ind){

        if(l==r)return v[ind][l];

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

        int lls=num[ind][s-1]-num[ind][l-1];

        int lse=num[ind][e]-num[ind][s-1];

        int rls=s-l-lls;

        int rse=e-s-lse+1;

        if(lse>=k)return query(l+lls,l+lls+lse-1,k,l,mid,ind+1);

        asum+=sum[ind][e]-(s>0?sum[ind][s-1]:0);

        return  query(mid+1+rls,mid+rls+rse,k-lse,mid+1,r,ind+1);

}

int main(){

        int T;

        scanf("%d",&T);

        for(int t=1;t<=T;t++){

                int n;

                scanf("%d",&n);

                for(int i=0;i<n;i++){

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

                        order[i]=v[0][i];

                        s[i]=(i>0?s[i-1]:0)+v[0][i];

                }

                sort(order,order+n);

                memset(num,0,sizeof(num));

                build(0,n-1,0);

                int q;

                scanf("%d",&q);

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

                for(int i=0;i<q;i++){

                        int l,r;

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

                        asum=0;

                        ll mid=query(l,r,((l+r)>>1)-l+1,0,n-1,0);

                        ll ans=mid*(((l+r)>>1)-l)-(r-((l+r)>>1))*mid-asum+(s[r]-(l>0?s[l-1]:0)-asum-mid);

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

                }

                puts("");

        }

}

  

你可能感兴趣的:(数据结构)