题意:

给出一个长度为\(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)\)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long LL;
  6. const int maxn = 100000 + 10;
  7. const int maxd = 20;
  8. int n;
  9. int sorted[maxn];
  10. int T[maxd][maxn], cnt[maxd][maxn];
  11. LL sum[maxd][maxn], pre[maxn];
  12. void build(int d, int L, int R) {
  13. int M = (L + R) / 2;
  14. int lsame = M - L + 1;
  15. for(int i = L; i <= R; i++)
  16. if(T[d][i] < sorted[M]) lsame--;
  17. int lpos = L, rpos = M + 1;
  18. for(int i = L; i <= R; i++) {
  19. if(i == L) { sum[d][i] = 0; cnt[d][i] = 0; }
  20. else { sum[d][i] = sum[d][i-1]; cnt[d][i] = cnt[d][i-1]; }
  21. if(T[d][i] < sorted[M] || (T[d][i] == sorted[M] && lsame)) {
  22. cnt[d][i]++;
  23. sum[d][i] += T[d][i];
  24. T[d+1][lpos++] = T[d][i];
  25. if(T[d][i] == sorted[M]) lsame--;
  26. } else T[d+1][rpos++] = T[d][i];
  27. }
  28. if(L < M) build(d + 1, L, M);
  29. if(M + 1 < R) build(d + 1, M + 1, R);
  30. }
  31. LL q_kth, q_sum;
  32. void query(int d, int L, int R, int qL, int qR, int k) {
  33. if(L == R) { q_kth = T[d][L]; q_sum += T[d][L]; return; }
  34. int M = (L + R) / 2;
  35. int numl;
  36. if(qL == L) numl = 0;
  37. else numl = cnt[d][qL - 1];
  38. int numr = cnt[d][qR];
  39. int num = numr - numl;
  40. if(num >= k) {
  41. query(d + 1, L, M, L + numl, L + numr - 1, k);
  42. } else {
  43. LL suml;
  44. if(qL == L) suml = 0;
  45. else suml = sum[d][qL - 1];
  46. q_sum += sum[d][qR] - suml;
  47. numl = qL - L - numl;
  48. numr = qR - L + 1 - numr;
  49. query(d + 1, M+1, R, M+1+numl, M+numr, k - num);
  50. }
  51. }
  52. int main()
  53. {
  54. int _; scanf("%d", &_);
  55. for(int kase = 1; kase <= _; kase++) {
  56. scanf("%d", &n);
  57. for(int i = 1; i <= n; i++) {
  58. scanf("%d", sorted + i);
  59. pre[i] = pre[i - 1] + sorted[i];
  60. T[0][i] = sorted[i];
  61. }
  62. sort(sorted + 1, sorted + 1 + n);
  63. build(0, 1, n);
  64. printf("Case #%d:\n", kase);
  65. int q; scanf("%d", &q);
  66. while(q--) {
  67. int l, r; scanf("%d%d", &l, &r);
  68. l++; r++;
  69. int k = (r - l) / 2 + 1;
  70. q_sum = 0;
  71. query(0, 1, n, l, r, k);
  72. LL ans = q_kth * k - q_sum;
  73. ans += (pre[r] - pre[l-1] - q_sum) - q_kth * (r - l + 1 - k);
  74. printf("%lld\n", ans);
  75. }
  76. printf("\n");
  77. }
  78. return 0;
  79. }

HDU 3473 Minimum Sum 划分树的更多相关文章

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

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

  2. HDU 3473 Minimum Sum (划分树)

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

  3. HDU 3473 Minimum Sum (划分树求区间第k大带求和)(转)

    题意:在区间中找一个数,求出该区间每个数与这个数距离的总和,使其最小 找的数字是中位数(若是偶数个,则中间随便哪个都可)接着找到该区间比此数大的数的总和 区间中位数可以使用划分树,然后在其中记录:每层 ...

  4. HDU 3473 Minimum Sum(划分树)

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  5. hdu 3473 Minimum Sum

    传送门 之前看挑战的时候看到一道分桶法的题目,其实我不是很明白分桶法应该怎么写.看到poj后面的讨论版上写着划分树裸题,而我以前就听说过了划分树,就干脆拿来学习一下.在写这篇博客的时候,其实我还是对这 ...

  6. HDU-3743 Minimum Sum,划分树模板

    Minimum Sum 被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数. 题意:找一个数使得这个数和区间内所有数的差的绝对值最小.输出最小值. 开始用线段树来了一发果断T了,然后各种 ...

  7. hdu 3473 裸的划分树

    思路: 用Sum[dep][i]记录从tree[po].l到i中进入左子树的和. #include<iostream> #include<algorithm> #include ...

  8. 【HDOJ】3473 Minimum Sum

    划分树解.主席树解MLE. /* 3473 */ #include <iostream> #include <sstream> #include <string> ...

  9. hdu 2665 Kth number(划分树模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ]  改变一下输入就可以过 http://poj.org/problem? ...

随机推荐

  1. Oracle ERP Interface堵住--Request Running too long time,查找Request执行的Sql

    Request Running too long time 堵住了INV Manager 导致INV Interface Pending 很多笔资料 Review 发现Request 实际执行SQL ...

  2. 通过Maven构建打包Spring boot,并将config配置文件提取到jar文件外

    如果通过不同的IDE打包,着实会觉得依赖性太大,并且容易出现错误,操作也比较复杂 同时,spring-boot-maven-plugin的使用感觉,相关配置太少,并且无法满足方便部署和运行的需求. 这 ...

  3. logback-spring.xml

    <?xml version="1.0" encoding="UTF-8"?><!--该日志将日志级别不同的log信息保存到不同的文件中--&g ...

  4. ABAP区别CLEAR、REFRESH、FREE

    CLEAR.REFRESH.FREE 内表:如果使用有表头行的内表,CLEAR 仅清除表格工作区域.例如 clear gs-school 清除工作区. 要重置整个内表而不清除表格工作区域,使用REFR ...

  5. .Net平台互操作技术:03. 技术验证

    上面两篇文章分别介绍了.Net平台互操作技术面临的问题,并重点介绍了通过P/Invoke调用Native C++类库的技术实现.光说不做是假把式,本文笔者将设计实验来证明P/Invoke调用技术的可行 ...

  6. Python3基础02(列表和字符串处理)

    str = 'Runoob'# 输出字符串print(str) # 输出第一个到倒数第二个的所有字符print(str[0:-1]) # 输出字符串第一个字符print(str[0]) # 输出从第三 ...

  7. vue搭建骨架屏步骤配置

    1.什么是骨架屏幕? 在页面加载数据之前,有一段空白时间,要么用loading加载,要么就用骨架屏. 在开发webapp的时候总是会受到首屏加载时间过长的影响,主流的解决方法是在载入完成之前显示loa ...

  8. mysql-新增、更新、删除语句

    1.插入数据: INSERT INTO t_book VALUES(NULL,'我爱我家',20,'张三',1); INSERT INTO t_book(id,bookName,price,autho ...

  9. HDU 2639 Bone Collector II (01背包,第k解)

    题意: 数据是常规的01背包,但是求的不是最大容量限制下的最佳解,而是第k佳解. 思路: 有两种解法: 1)网上普遍用的O(V*K*N). 2)先用常规01背包的方法求出背包容量限制下能装的最大价值m ...

  10. CodeForces 52C Circular RMQ (线段树)

    线段树区间更新维护最小值...记得下放标记... 如果线段树上的一个完整区间被修改,那么最小值和最大值增加相应的值后不变, 会改变是因为一部分改变而另外一部分没有改变所以维护一下就好. 询问的时候也要 ...