题意:在区间中找一个数,求出该区间每个数与这个数距离的总和,使其最小

找的数字是中位数(若是偶数个,则中间随便哪个都可)接着找到该区间比此数大的数的总和

区间中位数可以使用划分树,然后在其中记录:每层的 1-i 中划分到左区间的总和

划分树:

划分树是一种基于线段树的数据结构。主要用于快速求出(在log(n)的时间复杂度内)序列区间的第k大值 。

划分树和归并树都是用线段树作为辅助的,原理是基于快排 和归并排序 的。

划分树的建树过程基本就是模拟快排过程,取一个已经排过序的区间中值,然后把小于中值的点放左边,大于的放右边。并且记录d层第i个数之前(包括i)小于中值的放在左边的数。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define dir(a,b) (a>>b)
const int Max=1e5+;
int orval[Max];
int dsegtr[][Max];//记录第i层划分树的序列
int lele[][Max];//记录第i层的1-i划分到左子树的元素个数(包括i)
long long sum[][Max],psum[Max],lsum;//每层的1-i中划分到左区间的总和
void Create(int sta,int enn,int cur)
{
int mid=dir(sta+enn,);
int lsame=mid-sta+;//此区间左边不小于orval[mid]的个数
int lsta=sta,rsta=mid+;
for(int i=sta; i<=mid; ++i)
{
if(orval[i]<orval[mid])
lsame--;
}
for(int i=sta; i<=enn; ++i)//给下一层赋值
{
sum[cur][i]=sum[cur][i-];
if(i==sta)
{
lele[cur][i]=;//表示[l, i]内有多少个数分到左边
}
else
{
lele[cur][i]=lele[cur][i-]; }
if(dsegtr[cur][i]==orval[mid])
{
if(lsame)
{
sum[cur][i]+=dsegtr[cur][i];
lsame--;
lele[cur][i]++;
dsegtr[cur+][lsta++]=dsegtr[cur][i];//相当于移动元素到左边
}
else
{
dsegtr[cur+][rsta++]=dsegtr[cur][i];//相当于移动元素到右边
}
}
else if(dsegtr[cur][i]<orval[mid])
{
sum[cur][i]+=dsegtr[cur][i];
lele[cur][i]++;
dsegtr[cur+][lsta++]=dsegtr[cur][i];
}
else
{
dsegtr[cur+][rsta++]=dsegtr[cur][i];
}
}
if(sta==enn)
return;
Create(sta,mid,cur+);
Create(mid+,enn,cur+);
return;
}
int Query(int sta,int enn,int cur,int lef,int rig,int k)
{
int lsame;//[sta, lef)内将被划分到左子树的元素数目
int rsame;//[lef,rig]内将被划分到左子树的元素数目 关键
int mid=dir(sta+enn,);
if(sta==enn)
return dsegtr[cur][sta];
if(sta==lef)//特判
{
lsame=;
rsame=lele[cur][rig];
}
else
{
lsame=lele[cur][lef-];
rsame=lele[cur][rig]-lsame;
}
if(k<=rsame)
{
return Query(sta,mid,cur+,sta+lsame,sta+lsame+rsame-,k);//关键
}
else
{
lsum+=sum[cur][rig]-sum[cur][lef-];//所求值不在左区间
return Query(mid+,enn,cur+,mid-sta++lef-lsame,mid-sta++rig-lsame-rsame,k-rsame);//关键
}
}
long long Solve(long long temp,int rig,int lef,int k)
{
long long resr=psum[rig]-psum[lef-]-lsum-temp-(long long)(rig-lef+-k)*temp;
long long resl=(long long)(k-)*temp-lsum;
return resr+resl;
}
int main()
{
int n,m,t,coun=;
int lef,rig;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=;i<;++i)
sum[i][]=0ll;
psum[]=0ll;
for(int i=; i<=n; ++i)
{
scanf("%d",&orval[i]);
psum[i]=psum[i-]+orval[i];
dsegtr[][i]=orval[i];
sum[][i]=sum[][i-]+orval[i];
}
sort(orval+,orval+n+);
Create(,n,);
scanf("%d",&m);
printf("Case #%d:\n",++coun);
for(int i=; i<m; ++i)
{
lsum=0ll;
scanf("%d %d",&lef,&rig);
lef++,rig++;
int temp=Query(,n,,lef,rig,(rig-lef+>>));
printf("%I64d\n",Solve(temp,rig,lef,(rig-lef+>>)));
}
printf("\n");
}
return ;
}

参考:http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html

HDU 3473 Minimum Sum (划分树求区间第k大带求和)(转)的更多相关文章

  1. [hdu2665]Kth number(划分树求区间第k大)

    解题关键:划分树模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cs ...

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

    http://acm.hdu.edu.cn/showproblem.php?pid=3473 划分树模板题目,需要注意的是划分树的k是由1开始的 划分树: 参考:http://blog.csdn.ne ...

  3. HDU 3473 Minimum Sum 划分树

    题意: 给出一个长度为\(n(1 \leq n \leq 10^5)\)的序列\(a\) 有若干次查询l r:找到一个\(x\)使得\(\sum \limits_{l \leq i \leq r} \ ...

  4. [csu/coj 1080]划分树求区间前k大数和

    题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数 ...

  5. HDOJ题目4417 Super Mario(划分树求区间比k小的个数+二分)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  6. [poj2104]kth-number(归并树求区间第k大)

    复杂度:$O(nlog^3n)$ #include<cstdio> #include<cstring> #include<algorithm> #include&l ...

  7. poj 2104 主席树(区间第k大)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 44940   Accepted: 14946 Ca ...

  8. POJ2761---Feed the dogs (Treap求区间第k大)

    题意 就是求区间第k大,区间 不互相包含. 尝试用treap解决一下 第k大的问题. #include <set> #include <map> #include <cm ...

  9. HDU 3473 Minimum Sum (划分树)

    题意:给定一个数组,有Q次的询问,每次询问的格式为(l,r),表示求区间中一个数x,使得sum = sigma|x - xi|最小(i在[l,r]之间),输出最小的sum. 思路:本题一定是要O(nl ...

随机推荐

  1. phantom的使用

    phantom页面加载 通过Phantomjs,一个网页可以被加载.分析和通过创建网页对象呈现,访问我的博客园地址:http://www.cnblogs.com/paulversion/p/83938 ...

  2. jetty;linux 目录结构

    [说明]今天看了看jetty这个web容器,上午看基础理论框架知识(后面半点没用到),下午下载了jetty,并且在上面部署了一个war应用,晚上在做eclipses整合jetty的时候出现了问题,下载 ...

  3. 1624 取余最长路(set)

    1624 取余最长路 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱 ...

  4. 内网网络摄像机(RTSP/IPC/NVR)如何能在公网进行RTMP/HLS/HTTP-FLV直播

    一.背景需求 传统监控行业里不管是设备端.服务器端亦或是客户端都在一个内网里面.而且现在的大部分监控方案都是这样的格局,小到一个公司范围内的监控,再到一个园区.一个仓库监控.一个农业园林监控.一个养殖 ...

  5. VS2010程序崩溃- APPCRASH

    使用VS2010打开某个项目出现错误,程序崩溃:还不是全部的项目:开始以为是那个项目本身有什么问题,查了很久发现不是这样的 程序崩溃提示 问题签名: 问题事件名称: APPCRASH 应用程序名: d ...

  6. Python如何实现单例模式?其他23种设计模式python如何实现?

    #使用__metaclass__(元类)的高级python用法 class Singleton2(type): def __init__(cls, name, bases, dict): super( ...

  7. Java并发—线程池框架Executor总结(转载)

    为什么引入Executor线程池框架 new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞 ...

  8. phonegap file api

    https://github.com/chrisben/imgcache.js/tree/master/examples 1.FILE API file api最大的两个功能是download和upl ...

  9. iOS学习之库

    一.什么是库 库是程序代码的集合,是共享程序代码的一种方式. 二.库的分类 根据源代码的公开情况,库可以分为2种类型. 1.开源库 公开源代码,能看到具体实现. 比如,SDWebImage.AFNet ...

  10. maven 项目打包时无法解析读取properties文件

    在做项目时遇见一个问题,无法解析properties文件的 内容 异常为 Could not resolve placeholder ......... 在此之前均有做相关的 配置 但是从未出现过如上 ...