• 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

     

    #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:
    ",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
    ",ans);
                    }
                    puts("");
            }
    }
    

      

  • 相关阅读:
    Win32 服务进程和单实例实现
    Win32开发(命令行参数处理)
    动态链接库
    Poco 配置文件读取
    Delphi 窗口消息
    【原创】用phantomjs爬取网页数据
    【原创】搭建spark环境二
    【原创】搭建spark环境
    python爬虫——抓取电影天堂电影信息
    【学习笔记】Python 小练习—数据挖掘
  • 原文地址:https://www.cnblogs.com/xuesu/p/4296779.html
Copyright © 2020-2023  润新知