Minimum Sum

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3611    Accepted Submission(s): 829

Problem Description
You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you some intervals [l, r]. For each interval, you need to find a number x to make as
small as possible!
 
Input
The first line is an integer T (T <= 10), indicating the number of test cases. For each test case, an integer N (1 <= N <= 100,000) comes first. Then comes N positive integers x (1 <= x <= 1,000, 000,000) in the next line. Finally, comes an integer Q (1 <=
Q <= 100,000), indicting there are Q queries. Each query consists of two integers l, r (0 <= l <= r < N), meaning the interval you should deal with.

 
Output
For the k-th test case, first output “Case #k:” in a separate line. Then output Q lines, each line is the minimum value of  . Output a blank line after every
test case.
 
Sample Input
2

5
3 6 2 2 4
2
1 4
0 2

2
7 7
2
0 1
1 1

 
Sample Output
Case #1:
6
4

Case #2:
0
0

 
Author
standy
 
Source

题意:

给你一个区间,让你找出其中一个值,让所有值与它相减的绝对值的和最小。

思路:

于是成了找出其中的中间值减去最小,最开始简单粗暴地超时。然后发现求绝对值有点麻烦,于是在建树和查找的过程中找出比中间值小的数的和,然后分类计算吧。

感觉最开始没有考虑好方案,太随意了。

/*
hdu 3473
最开始直接算TL,然后发现由于是计算绝对值,在建树的时候需要记录比你查找的值小的和,
然后分开计算即可
*/ #include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <Map>
using namespace std;
typedef long long ll;
typedef long double ld; using namespace std; const int maxn = 100010; int tree[20][maxn];
int sorted[maxn];
int toleft[20][maxn];
ll sum[maxn];
ll lsum[20][maxn];
ll tsum; void build(int l,int r,int dep) //模拟快排 并记录左树中比i小的个数
{
if(l == r)
return;
int mid = (l+r)>>1;
int same = mid-l+1;//可能有很多值与中间那个相等,但不一定被分到左边
for(int i = l;i <= r;i++)
{
if(tree[dep][i] < sorted[mid])
same--;
}
int lpos = l;
int rpos = mid+1;
for(int i = l;i <= r;i++)
{
if(tree[dep][i] < sorted[mid]){
tree[dep+1][lpos++] = tree[dep][i];
lsum[dep][i] = lsum[dep][i-1] + tree[dep][i];
}
else if(tree[dep][i] == sorted[mid] && same > 0)
{
tree[dep+1][lpos++] = tree[dep][i];
lsum[dep][i] = lsum[dep][i-1] + tree[dep][i];
same --;
}
else
{
tree[dep+1][rpos++] = tree[dep][i];
lsum[dep][i] = lsum[dep][i-1];
}
toleft[dep][i] = toleft[dep][l-1] + lpos -l; }
build(l,mid,dep+1);
build(mid+1,r,dep+1);
} int query(int L,int R,int l,int r,int dep,int k)
{
if(l == r)
return tree[dep][l];
int mid = (L+R)>>1; int cnt = toleft[dep][r]-toleft[dep][l-1]; //所查找区间放在左树中的个数
if(cnt >= k)
{ //得到l左边放到左子树的个数,加上L即是开始位置
int lpos = L+toleft[dep][l-1]-toleft[dep][L-1];
int rpos = lpos+cnt-1; return query(L,mid,lpos,rpos,dep+1,k);
}
else
{ //R-r可以得出后面空出了多少位置
int rpos = r+toleft[dep][R]-toleft[dep][r];
int lpos = rpos-(r-l-cnt);
tsum += lsum[dep][r] - lsum[dep][l-1];
return query(mid+1,R,lpos,rpos,dep+1,k-cnt);
}
} int main()
{
int n,m,T;
int cas = 1;
scanf("%d",&T);
while(T--)
{ scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d",&sorted[i]);
sum[i] = sum[i-1]+sorted[i];
tree[0][i] = sorted[i];
}
sort(sorted+1,sorted+n+1);
build(1,n,0);
scanf("%d",&m);
int l,r;
printf("Case #%d:\n",cas++);
while(m--)
{
scanf("%d%d",&l,&r);
l++;r++;tsum = 0;
ll k =(r-l)/2+1;
ll ans = 0;
ll aver = query(1,n,l,r,0,k);
ans = sum[r]-sum[l-1]-aver*(r-l+1-k)-tsum-aver;
ans += (k-1)*aver-tsum;
printf("%I64d\n",ans);
}
puts("");
}
return 0;
}

  

hdu 3473 划分树的更多相关文章

  1. HDU 4417 (划分树+区间小于k统计)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4417 题目大意:给定一个区间,以及一个k值,求该区间内小于等于k值的数的个数.注意区间是从0开始的 ...

  2. hdu 4251 划分树

    思路:裸的划分树 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath ...

  3. hdu 2665 划分树

    思路:裸的划分树 #include<iostream> #include<algorithm> #include<cstring> #include<cstd ...

  4. hdu 4417 划分树

    思路:二分枚举区间第k大.用划分树查找是否符合要求的高度. #include<iostream> #include<algorithm> #include<cstdio& ...

  5. HDU 4417 划分树写法

    Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability re ...

  6. HDU 4417 划分树+二分

    题意:有n个数.m个询问(l,r,k),问在区间[l,r] 有多少个数小于等于k. 划分树--查找区间第k大的数.... 利用划分树的性质.二分查找在区间[l,r]小于等于k的个数. 假设在区间第 i ...

  7. hdu 2665 划分树模板题(可作为模板)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

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

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

  9. HDU 3473 Minimum Sum (划分树)

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

随机推荐

  1. css3 文字的设置

    1.text-shadow 有3个length参数,第1个表示水平偏移,第2个表示垂直偏移,第3个表示模糊(可选) .text11{text-shadow: 3px 3px 5px #f00 ;col ...

  2. 第四十八条:如果需要精确的答案,请避免使用float和double

    让一个float或者double精确的表示0.1或者10的任何负数次方值都是不可能.float和double它们执行二进制浮点运算, 它们是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的 ...

  3. (function(root,factory){})(this,function($){}) 一个立即执行的匿名函数自调

    因为新公司用到ocx 我就开始看原来的代码 无意中发现这个 可能原来比较low吗(虽然现在也很low吧)没发现这个东东 还可以这样写 于是乎我开始了探索 完整代码如下 HTML <div id= ...

  4. mui对话框事件

    mui.confirm('生成成功,是否跳转到订单页面?','',['跳转','取消'],function(e){ if(e.index==0){ //点击跳转 }else if(e.index==1 ...

  5. Entity Framework Core Code First

    参考地址:https://docs.microsoft.com/zh-cn/ef/core/get-started/aspnetcore/new-db

  6. MySQL ID排序乱了的解决办法

    可能在整理表中数据的时候删除了某一行数据,导致ID空缺,下面是我用到的解决办法:(请先备份,MySQL备份方法见 MySQL->MySQL备份) 使用ALTER DROP删除原有的ID字段: A ...

  7. jq 滚轮监听事件

    windowAddMouseWheel(); function windowAddMouseWheel() { var i = 0; var scrollFunc = function (e) { e ...

  8. Spring Security入门(2-3)Spring Security 的运行原理 4 - 自定义登录方法和页面

    参考链接,多谢作者: http://blog.csdn.net/lee353086/article/details/52586916 http元素下的form-login元素是用来定义表单登录信息的. ...

  9. gradle入门(1-1)gradle的概念和使用

    一.Gradle是什么 Gradle是一种Java应用构建工具,它采用领域特定语言 Groovy 语法实现配置. 1.Gradle的基本概念 项目:项目的配置 即 build.gradle. 任务:任 ...

  10. 表单中各种input汇总

    html表单 表单用于搜集不同类型的用户输入,表单由不同类型的标签组成,相关标签及属性用法如下: 1.<form>标签 定义整体的表单区域 action属性 定义表单数据提交地址 meth ...