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

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

区间中位数可以使用划分树,然后在其中记录:每层的 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. [Docker]学习笔记--搭建gitlab

    Gitlab 是一个用于仓库管理系统的开源项目.使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 详细介绍可以参照官网,https://about.gitlab.com/ 今天主要是通过 ...

  2. 作为一名合格的JAVA程序员需要点亮那些技能树?

    以下是出现次数超过100的一些技能,大家可以做一个参考. Spring 299 MySQL 290 JavaScript 216Linux 165J2EE 151设计模式 148Struts2 138 ...

  3. [转载]$(document).ready(function(){});

    转载自:http://www.cnblogs.com/king-sheng/archive/2012/01/06/2313980.html $(document).ready(function() 页 ...

  4. Qt 如何像 VS 一样创建项目模版?

    qt 存储模版路径位置:Qt\Qt5.9.5\Tools\QtCreator\share\qtcreator\templates\wizards 在里面随意复制一个模版,修改三项即可在 qt 中显示该 ...

  5. 常用的JS代码块收集

    /**数组去重一*/ (function (arr) { arr = arr.sort(); for (var i = 0; arr[i]; i++) { if (arr[i] === arr[i + ...

  6. MySQL中一致性非锁定读

    一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(multi versionning)的方式来读取当前执行时间数据库中行的数据,如果读取的行 ...

  7. HDFS权限

    1.1 超级用户 启动namenode服务的用户就是超级用户, 该用户的组是supergroup 1.2 文件权限管理   1.2.1 创建时的owner和group 文件或者目录被创建之时,服从BS ...

  8. 001-OSI七层模型,TCP/IP五层模型

    一.概述 OSI(Open System Interconnection)参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型. OSI/ ...

  9. comboBox绑定字典Dictionary 获取value中的值

    第一种 最简洁的方法 Dictionary<string, string> list = new Dictionary<string, string> { {"thi ...

  10. adb通过TCP/IP连接提示 unable to connect to *, Connection refused的解决方法

    通过串口连接板子进入命令行,然后执行: su setprop service.adb.tcp.port 5555 stop adbd start adbd