题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1367

好题啊!论文上的题;

论文上只给出了不下降序列的求法:

先考虑特殊情况,如果原序列上升,那么答案序列相同即可,如果下降,那么答案序列取中位数;

那么对于跌宕起伏的原序列,可以先一个一个加入元素,每次加入一个作为一个新区间,中位数是自己;

因为答案序列要不下降,所以当前区间的中位数比前一个区间大的时候就要合并,归纳可知(感性理解)整个区间的答案是它们的中位数;

论文中有严谨证明:https://wenku.baidu.com/view/20e9ff18964bcf84b9d57ba1.html

取中位数可以用一个大小是全体一半的大根堆,又要合并,所以就用可并堆;

那么求上升序列呢?

有个很巧妙的技巧,就是把原序列 t[i] = t[i] - i,然后对于这个序列求不下降序列;

那么得到答案序列后,把答案序列的每个元素都 + i,就得到一个上升序列,而差值的和还是不变的。

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. int const maxn=1e6+;
  8. int n,t[maxn],l[maxn],r[maxn],rt[maxn],siz[maxn],num[maxn];
  9. int ls[maxn],rs[maxn],dis[maxn];
  10. ll ans;
  11. int abb(int x){return x>?x:-x;}
  12. int merge(int x,int y)
  13. {
  14. if(!x||!y)return x+y;
  15. if(t[x]<t[y])swap(x,y);//维护大根堆
  16. rs[x]=merge(rs[x],y);
  17. siz[x]=siz[ls[x]]+siz[rs[x]]+;//+1
  18. if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
  19. if(rs[x])dis[x]=dis[rs[x]]+;
  20. else dis[x]=;
  21. return x;
  22. }
  23. int main()
  24. {
  25. scanf("%d",&n);
  26. for(int i=;i<=n;i++)scanf("%d",&t[i]),t[i]-=i;
  27. int nw=;
  28. for(int i=;i<=n;i++)
  29. {
  30. l[++nw]=r[nw]=i; rt[nw]=i;
  31. siz[rt[nw]]=num[nw]=;
  32. while(nw>&&t[rt[nw-]]>t[rt[nw]])
  33. {
  34. nw--;
  35. num[nw]+=num[nw+]; r[nw]=r[nw+];
  36. rt[nw]=merge(rt[nw],rt[nw+]);
  37. while(siz[rt[nw]]*>num[nw]+)//+1
  38. rt[nw]=merge(ls[rt[nw]],rs[rt[nw]]);
  39. }
  40. }
  41. for(int i=;i<=nw;i++)
  42. for(int j=l[i];j<=r[i];j++)ans+=abb(t[j]-t[rt[i]]);
  43. printf("%lld\n",ans);
  44. return ;
  45. }

bzoj 1367 [ Baltic 2004 ] sequence —— 左偏树的更多相关文章

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

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

  2. BZOJ 2809: [Apio2012]dispatching(左偏树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2809 题意: 思路:最简单的想法就是枚举管理者,在其子树中从薪水低的开始选起,但是每个节点都这样处理 ...

  3. BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆

    https://www.lydsy.com/JudgeOnline/problem.php?id=4003 感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始 ...

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

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

  5. bzoj 4003 [JLOI2015]城池攻占 —— 左偏树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4003 其实蛮简单的,首先一个城市只会被其子树中的骑士经过,启发我们 dfs 序用可并堆合并子 ...

  6. BZOJ1367: [Baltic2004]sequence(左偏树)

    Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 解题思路: 有趣的数学题. 首先确定序 ...

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

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

  8. 黄源河《左偏树的应用》——数字序列(Baltic 2004)

    这道题哪里都找不到. [问题描述] 给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| ...

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

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

随机推荐

  1. Linux系统硬软信息

    系统硬软信息 //获取根用户权限su //升级内核 yum update kernel

  2. Oracle 11g 字符集修改

    服务端字符集修改 1.确认服务端字符集 select userenv('language') from dual; 2.修改服务端字符集 首先以 DBA 身份登录 Oracle.Windows 系统下 ...

  3. BZOJ 2693: jzptab 莫比乌斯反演 + 积性函数 +筛法

    Code: #include<bits/stdc++.h> #define ll long long #define M 10001000 #define maxn 10200100 #d ...

  4. 个人总结的常用java,anroid网站

    http://blog.csdn.net/wanghao200906/article/details/49334987

  5. NOIP 2018 真・退役记

    目录 NOIp 2018 真・退役记 7.01 7.05 \(summary\) 7.12 7.18 7.26 - 7.27 8.2 8.3 8.3 8.7 8.9 8.20 8.24 8.27 8. ...

  6. [luogu4127 AHOI2009] 同类分布 (数位dp)

    传送门 Solution 裸数位dp,空间存不下只能枚举数字具体是什么 注意memset最好为-1,不要是0,有很多状态答案为0 Code //By Menteur_Hxy #include < ...

  7. 网络配置:IP+NETMASK+GATEWAY+DNS

    1.  IP IP地址(英语:Internet Protocol Address)是一种在Internet上的给主机编址的方式,也称为网际协议地址.常见的IP地址,分为IPv4与IPv6两大类. IP ...

  8. 初遇Java

    什么是JVM?JVM是java虚拟机(JVM Java Virtual Machine),java程序需要运行在虚拟机上,不同平台有自己的虚拟机,因此java语言可以跨平台. 什么是JRE?包括Jav ...

  9. ubuntu root用户登陆

    sudo vi /etc/lightdm/lightdm.conf   (如果没有该文件则创建,内容如下) [SeatDefaults] user-session=ubuntu greeter-ses ...

  10. 【Python实践-8】和为S的两个数字

    (剑指offer)输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 思路:选定第一个数字,然后遍历后面的数字求和并与S比 ...