【题目大意】

给定一个序列t1,t2,...,tn ,求一个递增序列z1<z2<...<zn , 使得R=|t1−z1|+|t2−z2|+...+|tn−zn| 的值最小。本题中,我们只需要求出这个最小的R值。

【思路】

-这个比加延迟标记的左偏树调试得还久……WA到死……

如果ti是递增的,我们只需要取zi=ti;

如果ti是递减的,我们只需要取ti的中位数。

所以我们将ti分割成若干个区间,维护每个区间的中位数。对于[L,R]的区间,我们存放[L,(L+R)/2]在堆中。具体如下操作:

(1)加入ti,将它作为一个单独的区间。

(2)比较前一个区间的中位数(即当前栈顶的最大值)和当前区间的中位数,如果前者小于后者,就将后者压入栈中。否则将前者弹出,和后者合并。注意的是如果两个区间的大小均为奇数(注意这里说的是区间大小,即L-R+1,而不是维护中位数的堆的大小),比如3和5合并,我们只需要存4个数字,而直接合并堆中存了5个,所以弹出堆顶。

(3)把合并后的堆作为当前区间,继续操作。

某种意义上的贪心思想。

我用的是左偏树,在左偏树里同时记录了L、R、size。

不过这样操作只会得到不下降,而不是递增。据说一开始输入t[i]时,t[i]-=i即可,没有会到意思orz

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<stack>
  6. #include<cmath>
  7. using namespace std;
  8. const int MAXN=+;
  9. typedef long long ll;
  10. struct node
  11. {
  12. int key,dis,size;
  13. int lson,rson,father;
  14. int L,R;
  15.  
  16. }ltree[MAXN];
  17. int n,z[MAXN];
  18. stack<int> S;
  19.  
  20. void pushup(int x)
  21. {
  22. int l=ltree[x].lson,r=ltree[x].rson;
  23. ltree[x].size=+ltree[l].size+ltree[r].size;
  24. }
  25.  
  26. void build(int rt,int x)
  27. {
  28. ltree[rt].key=x;
  29. ltree[rt].dis=(rt==)?-:;
  30. ltree[rt].size=(rt==)?:;
  31. //不要忘了当Rt=0的时候size为0
  32. ltree[rt].lson=ltree[rt].rson=;
  33. ltree[rt].father=ltree[rt].L=ltree[rt].R=rt;
  34. }
  35.  
  36. int merge(int x,int y)
  37. {
  38. if (x== || y==) return (x+y);
  39. if (ltree[x].key<ltree[y].key) swap(x,y);
  40. ltree[x].L=min(ltree[x].L,ltree[y].L);
  41. ltree[x].R=max(ltree[x].R,ltree[y].R);
  42. ltree[x].rson=merge(ltree[x].rson,y);
  43. int &l=ltree[x].lson,&r=ltree[x].rson;
  44. if (ltree[l].dis<ltree[r].dis) swap(l,r);
  45. if (r==) ltree[x].dis=;
  46. else ltree[x].dis=ltree[r].dis+;
  47. pushup(x);
  48. return x;
  49. }
  50.  
  51. int del(int rt)
  52. {
  53. int l=ltree[rt].lson,r=ltree[rt].rson;
  54. ltree[rt].dis=;
  55. ltree[rt].size=;
  56. ltree[rt].lson=ltree[rt].rson=;
  57. int ret=merge(l,r);
  58. ltree[ret].L=ltree[rt].L;
  59. ltree[ret].R=ltree[rt].R;
  60. return ret;
  61. }
  62.  
  63. void init()
  64. {
  65. scanf("%d",&n);
  66. for (int i=;i<=n;i++) scanf("%d",&z[i]),z[i]-=i;
  67. for (int i=;i<=n;i++) build(i,z[i]);
  68. build(,);
  69. }
  70.  
  71. void solve()
  72. {
  73. int before=z[];
  74. S.push();
  75. for (int i=;i<=n;i++)
  76. {
  77. int now=i;
  78. while (!S.empty())
  79. {
  80. int tail=S.top();
  81. if (ltree[now].key<ltree[tail].key)
  82. {
  83. S.pop();
  84. int tmp=merge(tail,now);
  85. now=tmp;
  86. while (ltree[now].size*>(ltree[now].R-ltree[now].L+)) now=del(now);
  87. //不要忘记了这里是ltree[now].R-ltree[now].L+2,一开始写成了+1
  88. if (S.empty())
  89. {
  90. S.push(now);
  91. break;
  92. }
  93. }
  94. else
  95. {
  96. S.push(now);
  97. break;
  98. }
  99. }
  100. }
  101. ll ans=;
  102. while (!S.empty())
  103. {
  104. int now=S.top();S.pop();
  105. for (int i=ltree[now].L;i<=ltree[now].R;i++) ans+=abs(z[i]-ltree[now].key);
  106. }
  107. printf("%lld",ans);
  108. }
  109.  
  110. int main()
  111. {
  112. init();
  113. solve();
  114. return ;
  115. }

【左偏树+贪心】BZOJ1367-[Baltic2004]sequence的更多相关文章

  1. bzoj1367 [Baltic2004]sequence 左偏树+贪心

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1367 题解 先考虑条件为要求不下降序列(不是递增)的情况. 那么考虑一段数值相同的子段,这一段 ...

  2. BZOJ1367 [Baltic2004]sequence 堆 左偏树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1367 题意概括 Description Input Output 一个整数R 题解 http:// ...

  3. BZOJ1367 [Baltic2004]sequence 【左偏树】

    题目链接 BZOJ1367 题解 又是一道神题,, 我们考虑一些简单的情况: 我们先假设\(b_i\)单调不降,而不是递增 对于递增序列\(\{a_i\}\),显然答案\(\{b_i\}\)满足\(b ...

  4. 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)

    1367: [Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Ou ...

  5. 【CF671D】Roads in Yusland(贪心,左偏树)

    [CF671D]Roads in Yusland(贪心,左偏树) 题面 洛谷 CF 题解 无解的情况随便怎么搞搞提前处理掉. 通过严密(大雾)地推导后,发现问题可以转化成这个问题: 给定一棵树,每条边 ...

  6. BZOJ1367 BOI2004Sequence(左偏树)

    首先考虑把bi和ai同时减i,问题变为非严格递增.显然如果a是一个递减序列,b序列所有数都取其中位数最优.于是划分原序列使得每一部分递减,然后考虑合并相邻两段.如果前一段的中位数<=后一段的中位 ...

  7. 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]

    题目传送门 数字序列 题目描述 给定一个整数序列 a1​,a2​,⋅⋅⋅,an​ ,求出一个递增序列 b1​<b2​<⋅⋅⋅<bn​ ,使得序列 ai​ 和 bi​ 的各项之差的绝对 ...

  8. [BOI2004]Sequence 数字序列(左偏树)

    PS:参考了黄源河的论文<左偏树的特点及其应用> 题目描述:给定一个整数序列\(a_1, a_2, - , a_n\),求一个递增序列\(b_1 < b_2 < - < ...

  9. Luogu P4331 [BOI2004]Sequence 数字序列 (左偏树论文题)

    清晰明了%%% Fairycastle的博客 个人习惯把size什么的存在左偏树结点内,这样在外面好写,在里面就是模板(只用修改update). 可以对比一下代码(好像也差不多-) MY CODE # ...

随机推荐

  1. CALayer---iOS-Apple苹果官方文档翻译之CALayer

    CHENYILONG Blog CALayer---iOS-Apple苹果官方文档翻译之CALayer CALayer /*技术博客http://www.cnblogs.com/ChenYilong/ ...

  2. textarea输入框随内容撑开高度

    原文链接 方法一(jquery): $('textarea').each(function () {  this.setAttribute('style', 'height:' + (this.scr ...

  3. koa源码阅读[3]-koa-send与它的衍生(static)

    koa源码阅读的第四篇,涉及到向接口请求方提供文件数据. 第一篇:koa源码阅读-0第二篇:koa源码阅读-1-koa与koa-compose第三篇:koa源码阅读-2-koa-router 处理静态 ...

  4. TinyOS在ubuntu 14.04下安装教程

    1:打开/etc/apt/sources.list 文件,在文件最底部添加安装源: deb http://tinyos.stanford.edu/tinyos/dists/ubuntu lucid m ...

  5. 安装Docker-ce

    Docker Engine改为Docker CE(社区版) 它包含了CLI客户端.后台进程/服务以及API.用户像以前以同样的方式获取.Docker Data Center改为Docker EE(企业 ...

  6. webgote的例子(5)Sql注入(Blog)

    SQL Injection - Stored (Blog) (本章内容):留言板的注入 看到这个页面先看以下这个页面是做什么的.进行正常的写入发现我每写一句话,其内容都会写到下面的entry里面 在尝 ...

  7. 集合框架之Set学习

    前言:         1.何为框架:可以理解为一个基础结构,在基础结构上进行进一步开发会变得很方便. 2.三种集合类型:集合(Set) :元素无序不可重复: 列表(List) :元素有序可重复: 映 ...

  8. C++学习笔记--从虚函数说开去

    虚函数与纯虚函数: 虚函数:在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数,virtual  函数返回类型  函数名(参数表){函数体;} ,实现多态性,通过指向派生类的基类 ...

  9. redis aof文件过大问题

    http://www.itnose.net/detail/6682725.html 最近新安装了一台redis,版本为redis-3.2.5 数据盘用的是固态硬盘. 之前用的是普通硬盘,redis日志 ...

  10. 产生随机数 random

    int rand(void); 返回 0 ------- RAND_MAX 之间的一个 int 类型整数,该函数为非线程安全函数.并且生成随机数的性能不是很好,已经不推荐使用.        void ...