HDU 3473 Minimum Sum 划分树
题意:
给出一个长度为\(n(1 \leq n \leq 10^5)\)的序列\(a\)
有若干次查询l r
:找到一个\(x\)使得\(\sum \limits_{l \leq i \leq r} \left | x-a_i \right |\)的值最小。
分析:
有这样一个结论:\(x\)为子序列的中位数时差的绝对值之和最小。
证明也很简单:
将序列中的每个元素对应到数轴上的点,\(x\)是数轴上一个动点。
设\(x\)左边有\(l\)个点,右边有\(r\)个点。
如果动点向右移动\(\Delta x\)距离(而且保证移动后左右两侧点数不变),那么目标值就会变化\(l \Delta x - r \Delta x\)。
如果\(l<r\),这个值会变小;如果\(l>r\),那么向左移动这个值会变小。
直到左右两侧点数相等。
对于这道题就可以很方便地计算出答案:计算出中位数的大小\(mid\),中位数左右两侧数字的个数\(cnt_l,cnt_r\)以及的对应的和\(sum_l,sum_r\)。
最终答案就是:\((mid \cdot cnt_l - sum_l) + (sum_r - mid \cdot cnt_r)\)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 10;
const int maxd = 20;
int n;
int sorted[maxn];
int T[maxd][maxn], cnt[maxd][maxn];
LL sum[maxd][maxn], pre[maxn];
void build(int d, int L, int R) {
int M = (L + R) / 2;
int lsame = M - L + 1;
for(int i = L; i <= R; i++)
if(T[d][i] < sorted[M]) lsame--;
int lpos = L, rpos = M + 1;
for(int i = L; i <= R; i++) {
if(i == L) { sum[d][i] = 0; cnt[d][i] = 0; }
else { sum[d][i] = sum[d][i-1]; cnt[d][i] = cnt[d][i-1]; }
if(T[d][i] < sorted[M] || (T[d][i] == sorted[M] && lsame)) {
cnt[d][i]++;
sum[d][i] += T[d][i];
T[d+1][lpos++] = T[d][i];
if(T[d][i] == sorted[M]) lsame--;
} else T[d+1][rpos++] = T[d][i];
}
if(L < M) build(d + 1, L, M);
if(M + 1 < R) build(d + 1, M + 1, R);
}
LL q_kth, q_sum;
void query(int d, int L, int R, int qL, int qR, int k) {
if(L == R) { q_kth = T[d][L]; q_sum += T[d][L]; return; }
int M = (L + R) / 2;
int numl;
if(qL == L) numl = 0;
else numl = cnt[d][qL - 1];
int numr = cnt[d][qR];
int num = numr - numl;
if(num >= k) {
query(d + 1, L, M, L + numl, L + numr - 1, k);
} else {
LL suml;
if(qL == L) suml = 0;
else suml = sum[d][qL - 1];
q_sum += sum[d][qR] - suml;
numl = qL - L - numl;
numr = qR - L + 1 - numr;
query(d + 1, M+1, R, M+1+numl, M+numr, k - num);
}
}
int main()
{
int _; scanf("%d", &_);
for(int kase = 1; kase <= _; kase++) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", sorted + i);
pre[i] = pre[i - 1] + sorted[i];
T[0][i] = sorted[i];
}
sort(sorted + 1, sorted + 1 + n);
build(0, 1, n);
printf("Case #%d:\n", kase);
int q; scanf("%d", &q);
while(q--) {
int l, r; scanf("%d%d", &l, &r);
l++; r++;
int k = (r - l) / 2 + 1;
q_sum = 0;
query(0, 1, n, l, r, k);
LL ans = q_kth * k - q_sum;
ans += (pre[r] - pre[l-1] - q_sum) - q_kth * (r - l + 1 - k);
printf("%lld\n", ans);
}
printf("\n");
}
return 0;
}
HDU 3473 Minimum Sum 划分树的更多相关文章
- HDU 3473 Minimum Sum 划分树,数据结构 难度:1
http://acm.hdu.edu.cn/showproblem.php?pid=3473 划分树模板题目,需要注意的是划分树的k是由1开始的 划分树: 参考:http://blog.csdn.ne ...
- HDU 3473 Minimum Sum (划分树)
题意:给定一个数组,有Q次的询问,每次询问的格式为(l,r),表示求区间中一个数x,使得sum = sigma|x - xi|最小(i在[l,r]之间),输出最小的sum. 思路:本题一定是要O(nl ...
- HDU 3473 Minimum Sum (划分树求区间第k大带求和)(转)
题意:在区间中找一个数,求出该区间每个数与这个数距离的总和,使其最小 找的数字是中位数(若是偶数个,则中间随便哪个都可)接着找到该区间比此数大的数的总和 区间中位数可以使用划分树,然后在其中记录:每层 ...
- HDU 3473 Minimum Sum(划分树)
Minimum Sum Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- hdu 3473 Minimum Sum
传送门 之前看挑战的时候看到一道分桶法的题目,其实我不是很明白分桶法应该怎么写.看到poj后面的讨论版上写着划分树裸题,而我以前就听说过了划分树,就干脆拿来学习一下.在写这篇博客的时候,其实我还是对这 ...
- HDU-3743 Minimum Sum,划分树模板
Minimum Sum 被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数. 题意:找一个数使得这个数和区间内所有数的差的绝对值最小.输出最小值. 开始用线段树来了一发果断T了,然后各种 ...
- hdu 3473 裸的划分树
思路: 用Sum[dep][i]记录从tree[po].l到i中进入左子树的和. #include<iostream> #include<algorithm> #include ...
- 【HDOJ】3473 Minimum Sum
划分树解.主席树解MLE. /* 3473 */ #include <iostream> #include <sstream> #include <string> ...
- hdu 2665 Kth number(划分树模板)
http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ] 改变一下输入就可以过 http://poj.org/problem? ...
随机推荐
- ruby YAML.load 和YAML.load_file区别
1. load( io ) Load a document from the current io stream. File.open( 'animals.yaml' ) { |yf| YAML::l ...
- 基于JAVA的设计模式之代理模式
概念 王宝强有一个经纪人叫宋喆,这个经纪人很吊,可以代理王宝强做一系列的事情,与粉丝活动.王宝强的微博维护.安排王宝强的行程以及什么什么等等.如果王宝强一个人做岂不是累死.通过这个代理人为王宝强节省了 ...
- 【踩坑】List 的陷阱
今天测试iReview项目数据的反馈,发现有些语句总无法执行. 经过调试排查后,发现List<自定义类>返回了空集"[]",却无法进入if语句里面,即 if (List ...
- ZR#331. 【18 提高 3】括号序列(栈)
题意 挺神仙的.首先$60$分暴力是比较好打的. 就是枚举左端点,看右端点能否是$0$ 但是这样肯定是过不了的,假如我们只枚举一次,把得到的栈记录下来 那么若区间$(l, r)$是可行的,那么$s_{ ...
- 复选框 省市区 联动(监听input的change事件)
需求:省市区三级包含复选框按钮以及文字描述.点击文字显示对应的下级地区,点击复选框选择对应的下级区域勾选. 分析:监听input的change事件当点击复选框省 选择对应的第一个市区,同时默认选中第 ...
- 关于Linux系统启动时出现UVD not responding, Trying to reset the vcpu问题的解决
本人的老古董笔记本!不知道什么时候显卡烧坏了 每次启动Linux的时候就会出现错误,信息如下: UVD not responding, trying to reset the VCPU! 讲道理,显卡 ...
- escape,encodeURI,encodeURIComponent 之间的区别和使用
escape(目前已经被淘汰)是对字符串(string)进行编码(而另外两种是对URL),不会对下列字符编码 ASCII字母 数字 @*/+ 最关键的是,当你需要对URL编码时,请忘记这个方法,这 ...
- 常用css和js组件
1 . input框中插入图标 <div class="col-sm-12 col-xs-12 setLineHeight"> <div class=" ...
- Python3+Selenium3+webdriver学习笔记7(选择多链接的结果、iframe、下拉框)
#!/usr/bin/env python# -*- coding:utf-8 -*- from selenium import webdriverfrom selenium.webdriver.co ...
- Java 继承与重写
1.类的继承 1)继承 父类:所有子类所共有的属性和行为 子类:子类所特有的属性和行为 通过extends关键字来实现类的继承 子类(Sub class)可以继承父类(Super class)的成员变 ...