我觉得我要改一下签名了……怎么会有窝这么啰嗦的人呢?

做这题需要先学习左偏树《左偏树的特点及其应用》 然后做一下POJ3666,这题的简单版。

思路:

考虑一下维护中位数的过程
原数组为A,找到的不降数列为B
当对于A的前n个数已经找好了最优解B[1…n],可知此时A被分成很多块,并被一些大顶堆记录,假设第i块有num个数,那么第i个堆维护这一块的最小的(num+1)/2个数,堆顶即为中位数。
假设已经处理好前7个数,被分为两块 ([a,b],c,d) ([h,e],f) (每一块按升序排列,[]中的数是堆里面维护的。
因为数列是不降的,所以b≤e
当新添加一个元素的时候,设为x,如果x≤e,将需要向前合并。
那么新的块应该是……分两种情况……
1.x>h ([h,x],e,f)
2.x<h ([x,h],e,f)

设新的中位数是val=max(h, x)  分类讨论一下可以发现改变的值是(e-val)+(val-x)

这里假设是([x,h],e,f)
当h<b时,需要继续向前合并。
合并之后是([x,h,a,b],c,d,e,f) (顺序已经不确定了,只能确定栈中元素和栈顶是b

可以发现大小为偶数的块和偶数的块合并,合并后的堆不需要弹出元素。
合并前([a,b],c,d) 的中位数是b ([x,h],e,f)的中位数是h, 合并后的中位数的b
可知答案改变都是发生在集合([x,h],e,f)中的,我们又知道b≤e(上面提到过),那么很容易得到答案是不变哒!(就是把(h-x)+(h-h)+(e-h)+(f-h)变成了(b-x)+(b-h)+(e-b)+(f-b),值是一样的

上面是偶数和偶数合并,继续讨论前一块奇数和后一块偶数合并。
设前一块是([a,b],c) 中位数是b,后一块是([d,e],f,g)中位数是e,合并后不需要弹出,中位数是b,类似上面的情况,我们可以得出b≤f,所以答案仍然不变。

前一块偶数,后一块奇数
([a,b],c,d)中位数是b ([e,f],g)中位数是f 合并后不需要弹出 中位数是b 其中(f<b≤g)
那么答案由([e,f],g)的改变产生,f的左右两边是可以抵消掉的,改变只会因为f,改变的值是b-f

前一块奇数,后一块奇数
设前一块是([a,b],c) 中位数是b,后一块是([d,e],f,)中位数是e 其中e<b≤f
合并后弹出元素b,中位数为max(a,e),设为val
那么答案改变就是b-e

到此,所有情况都讨论完了ˊ_>ˋ

结论:当一个块和前面的块合并时,如果当前块的数量为偶数,答案不变,否则答案增加(前一块的中位数-当前块的中位数)

代码:

  1. /*****************************************
  2. Problem: 3016 User: G_lory
  3. Memory: 12676K Time: 1797MS
  4. Language: G++ Result: Accepted
  5. *****************************************/
  6. #include <iostream>
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <algorithm>
  10. using namespace std;
  11.  
  12. const int N = ;
  13. const int INF = 0x5f5f5f5f;
  14. typedef long long ll;
  15.  
  16. struct LTree {
  17. int l, r, sz;
  18. int key, dis;
  19. bool operator<(const LTree lt) const {
  20. return key < lt.key;
  21. }
  22. } tr[N];
  23. int cnt_tr;
  24.  
  25. int NewTree(int k) {
  26. tr[++cnt_tr].key = k;
  27. tr[cnt_tr].l = tr[cnt_tr].r = tr[cnt_tr].dis = ;
  28. tr[cnt_tr].sz = ;
  29. return cnt_tr;
  30. }
  31.  
  32. int Merge(int x, int y) {
  33. if (!x || !y) return x + y;
  34. if (tr[x] < tr[y]) swap(x, y);
  35. tr[x].r = Merge(tr[x].r, y);
  36. if (tr[tr[x].l].dis < tr[tr[x].r].dis) swap(tr[x].l, tr[x].r);
  37. tr[x].dis = tr[tr[x].r].dis + ;
  38. tr[x].sz = tr[tr[x].l].sz + tr[tr[x].r].sz + ;
  39. return x;
  40. }
  41.  
  42. int Top(int x) {
  43. return tr[x].key;
  44. }
  45.  
  46. void Pop(int &x) {
  47. x = Merge(tr[x].l, tr[x].r);
  48. }
  49.  
  50. int root[N], num[N];
  51. void cal(int a[], int n, int ans[]) {
  52. int res;
  53. cnt_tr = res = ;
  54. int cnt = ;
  55. for (int i = ; i < n; ++i) {
  56. root[++cnt] = NewTree(a[i]);
  57. num[cnt] = ;
  58. while (cnt > && Top(root[cnt]) < Top(root[cnt-])) {
  59. cnt--;
  60. if (num[cnt+]&) res += Top(root[cnt]) - Top(root[cnt+]);
  61. root[cnt] = Merge(root[cnt], root[cnt+]);
  62. num[cnt] += num[cnt+];
  63. while (tr[root[cnt]].sz* > num[cnt]+) {
  64. Pop(root[cnt]);
  65. }
  66. int now = Top(root[cnt]);
  67.  
  68. }
  69. ans[i] = res;
  70. }
  71. }
  72.  
  73. int a[N], b[N], c[N];
  74. int in[N][N], de[N][N];
  75. int dp[N][N];
  76. int main() {
  77. //freopen("in", "r", stdin);
  78. int n, k;
  79. while (~scanf("%d%d",&n, &k) && n) {
  80. for (int i = ; i <= n; ++i) {
  81. scanf("%d", a+i);
  82. b[i] = a[i]-i;
  83. c[i] = -a[i]-i;
  84. }
  85. for (int i = ; i <= n; ++i) {
  86. cal(c+i, n-i+, de[i]+i);
  87. cal(b+i, n-i+, in[i]+i);
  88. }
  89. for (int i = ; i <= n; ++i) dp[][i] = INF;
  90. for (int i = ; i <= k; ++i) {
  91. dp[i][] = ;
  92. for (int j = ; j <= n; ++j) {
  93. dp[i][j] = INF;
  94. for (int p = ; p < j; ++p) {
  95. dp[i][j] = min(dp[i][j], dp[i-][p] + min(in[p+][j], de[p+][j]));
  96. }
  97. }
  98. }
  99. printf("%d\n", dp[k][n]);
  100. }
  101. return ;
  102. }

  

POJ3016-K-Monotonic(左偏树+DP)的更多相关文章

  1. 左偏树(DP)问题

    问题:A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ woul ...

  2. 『左偏树 Leftist Tree』

    新增一道例题 左偏树 Leftist Tree 这是一个由堆(优先队列)推广而来的神奇数据结构,我们先来了解一下它. 简单的来说,左偏树可以实现一般堆的所有功能,如查询最值,删除堆顶元素,加入新元素等 ...

  3. Monkey King(左偏树 可并堆)

    我们知道如果要我们给一个序列排序,按照某种大小顺序关系,我们很容易想到优先队列,的确很方便,但是优先队列也有解决不了的问题,当题目要求你把两个优先队列合并的时候,这就实现不了了 优先队列只有插入 删除 ...

  4. POJ3666-Making the Grade(左偏树 or DP)

    左偏树 炒鸡棒的论文<左偏树的特点及其应用> 虽然题目要求比论文多了一个条件,但是……只需要求非递减就可以AC……数据好弱…… 虽然还没想明白为什么,但是应该觉得应该是这样——求非递减用大 ...

  5. k短路模板(洛谷P2483 [SDOI2010]魔法猪学院)(k短路,最短路,左偏树,priority_queue)

    你谷数据够强了,以前的A*应该差不多死掉了. 所以,小伙伴们快来一起把YL顶上去把!戳这里! 俞鼎力的课件 需要掌握的内容: Dijkstra构建最短路径树. 可持久化堆(使用左偏树,因其有二叉树结构 ...

  6. 洛谷P1552 [APIO2012] 派遣 [左偏树,树形DP]

    题目传送门 忍者 Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都 ...

  7. Luogu P1552 [APIO2012]派遣【左偏树】By cellur925

    题目传送门 $Chat$ 哈哈哈我xj用dfs序乱搞竟然炸出了66分....(其实还是数据水,逃) $Sol$ 首先我们应该知道,一个人他自己的满意度与他子树所有节点的领导力是无关的,一个人的满意度受 ...

  8. BZOJ 1455 罗马游戏 ——左偏树

    [题目分析] 左偏树的模板题目,大概就是尽量维护树的深度保持平衡,以及尽可能的快速合并的一种堆. 感觉和启发式合并基本相同. 其实并没有快很多. 本人的左偏树代码自带大常数,借鉴请慎重 [代码] #i ...

  9. 【BZOJ-1455】罗马游戏 可并堆 (左偏树)

    1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1355  Solved: 561[Submit][Status][Discuss] ...

随机推荐

  1. DevSecOps 实施篇!系列(二)

    想在自己公司建立 DevSecOps 计划?没问题,企业规模无论大小,都可轻松实现.这里有5个基本的 DevSecOps 原则可以帮助你启动.当然,如果你对 DevSecOps 还不太熟悉,不妨先看看 ...

  2. IDEA 创建maven-web project失败一例

    今天使用IDEA创建WEB-APP总是失败,经排查原来是MAVEN环境没配置好!!! 配置: M2_HOME--->maven解压目录 path---->%M2_HOME%\bin\

  3. iOS中关于KVC与KVO知识点

    iOS中关于KVC与KVO知识点 iOS中关于KVC与KVO知识点  一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCodin ...

  4. linux系统相关的任务[fg、bg、jobs、&、ctrl + z]

    转自: http://blog.chinaunix.net/space.php?uid=20697318&do=blog&id=1891382 fg.bg.jobs.&.ctr ...

  5. log4j:ERROR A "org.jboss.logging.appender.FileAppender" object is not assignable to a "org.apache.lo .

    log4j:ERROR A "org.jboss.logging.appender.FileAppender" object is not assignable to a &quo ...

  6. linux应用程序问题

    ---- 1 ----

  7. 【HDOJ】1914 The Stable Marriage Problem

    稳定婚姻问题,Gale-Shapley算法可解. /* 1914 */ #include <iostream> #include <sstream> #include < ...

  8. 推荐:ThoughtWorks(中国)程序员读书雷达

    部分转自张逸的博客:http://agiledon.github.io/blog/2013/04/17/thoughtworks-developer-reading-radar/ 长久以来一直对程序员 ...

  9. SSMS错误代码大全

    0 操作成功完成. 1 功能错误. 2 系统找不到指定的文件. 3 系统找不到指定的路径. 4 系统无法打开文件. 5 拒绝访问. 6 句柄无效. 7 存储控制块被损坏. 8 存储空间不足,无法处理此 ...

  10. Rman实现数据库迁移

    Rman实现数据库迁移(从库A迁移到库B)环境:服务器A:Oracle10g+AS3服务器B:Oracle10g+AS4准备工作: 1 在数据库B上建立与库A相同的目录结构(若由于磁盘空间等原因可以用 ...