码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-02-21 00:14:26      阅读:355      评论:0      收藏:0      [点我收藏+]

标签:

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

 技术分享

 

#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("");
        }
}

  

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

标签:

原文地址:http://www.cnblogs.com/xuesu/p/4296779.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!