可并堆试水--BZOJ1367: [Baltic2004]sequence
n<=1e6个数,把他们修改成递增序列需把每个数增加或减少的总量最小是多少?
方法一:可以证明最后修改的每个数一定是原序列中的数!于是$n^2$DP(逃)
方法二:把$A_i$改成$A_i-i$,变论文题:论文
大概证明是这样的:考虑合并两个区间的答案,假如一个区间答案是{u,u,u,……,u},另一个是{v,v,v,……,v},那合并之后,如果u<=v最优就{u,u,……,u,v,……,v};如果u>v,假设最优是
{b1,b2,……,bn,bn+1,……,bm},那么一定有bn<=u,否则把前半部分改成{u,u,……,u}不会更差。同理bn+1>=v。
这里有个不懂的地方:
因此可以把他改成{bn,bn,……,bn,bn+1,……,bn+1},不会更差。可以用几何意义感性理解一下:左边离u越近越优,右边离v越近越优。
然后由于bn<=u,bn+1>=v,本着“bn能大就大,bn+1能小就小”的原则让bn=bn+1。于是合并后的最优解为{w,w,w,……,w},最优的w是谁呢?肯定是整个区间的中位数啦。
然后就可以可并堆做一波合并了,因为这里合并后中位数只会变小,可以维护一个区间的一半小的数或一半大的数,合并两个区间时,如果两个区间大小都是奇数,则堆里会多出一个数,删之。
可并堆常需合并特定点所在的堆,因此常与并查集连用。千万别并查集懵逼了!!因为并查集操作失误调了一晚上。。
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
//#include<assert.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n;
#define maxn 1000011
int root[maxn];
int find(int x) {return x==root[x]?x:(root[x]=find(root[x]));}
struct leftist
{
struct Node
{
int v,ls,rs,dis,size;
}a[maxn];
int size;
leftist() {a[].dis=-;}
int merge(int x,int y)
{
if (!x || !y) return x^y;
if (a[x].v<a[y].v) {int t=x; x=y; y=t;}
a[x].rs=merge(a[x].rs,y);
if (a[a[x].ls].dis<a[a[x].rs].dis) {int t=a[x].ls; a[x].ls=a[x].rs; a[x].rs=t;}
a[x].dis=a[a[x].rs].dis+;
a[x].size=a[a[x].ls].size+a[a[x].rs].size+;
return x;
}
void push(int x,int &root,int val)
{
a[x].v=val; a[x].ls=a[x].rs=a[x].dis=; a[x].size=;
root=merge(root,x);
}
int top(int root) {return a[root].v;}
void pop(int &root) {root=merge(a[root].ls,a[root].rs);}
}q; int a[maxn],sta[maxn],die[maxn],top;
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]),a[i]-=i;
for (int i=;i<=n;i++)
{
q.push(i,root[i],a[i]); int x,y;
while (top && q.top(x=find(root[sta[top]]))>q.top(y=find(root[i])))
{
bool flag=;
if (((sta[top]-sta[top-])&) && ((i-sta[top])&)) flag=;
root[x]=root[y]=q.merge(x,y); x=root[x];
if (flag) die[x]=,q.pop(root[x]),root[root[x]]=root[x];
top--;
}
sta[++top]=i;
}
#define LL long long
LL ans=;
for (int i=;i<=n;i++) ans+=fabs(a[i]-q.top(find(root[i])));
printf("%lld\n",ans);
return ;
}
可并堆试水--BZOJ1367: [Baltic2004]sequence的更多相关文章
- BZOJ1367 [Baltic2004]sequence 堆 左偏树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1367 题意概括 Description Input Output 一个整数R 题解 http:// ...
- BZOJ1367 [Baltic2004]sequence 【左偏树】
题目链接 BZOJ1367 题解 又是一道神题,, 我们考虑一些简单的情况: 我们先假设\(b_i\)单调不降,而不是递增 对于递增序列\(\{a_i\}\),显然答案\(\{b_i\}\)满足\(b ...
- BZOJ1367 [Baltic2004]sequence
现学的左偏树...这可是道可并堆的好题目. 首先我们考虑z不减的情况: 我们发现对于一个区间[l, r],里面是递增的,则对于此区间最优解为z[i] = t[i]: 如果里面是递减的,z[l] = z ...
- BZOJ1367: [Baltic2004]sequence(左偏树)
Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 解题思路: 有趣的数学题. 首先确定序 ...
- bzoj1367 [Baltic2004]sequence 左偏树+贪心
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1367 题解 先考虑条件为要求不下降序列(不是递增)的情况. 那么考虑一段数值相同的子段,这一段 ...
- BZOJ1367——[Baltic2004]sequence
1.题目大意:给一个序列t,然后求一个序列z,使得$|z1-t1|+|z2-t2|+...+|zn-tn|$的值最小,我们只需要求出这个值就可以了,并且z序列是递增的 2.分析:这道题z序列是递增的, ...
- 【bzoj1367】[Baltic2004]sequence
2016-05-31 17:31:26 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1367 题解:http://www.cnblogs.co ...
- POJ 2502 - Subway Dijkstra堆优化试水
做这道题的动机就是想练习一下堆的应用,顺便补一下好久没看的图论算法. Dijkstra算法概述 //从0出发的单源最短路 dis[][] = {INF} ReadMap(dis); for i = 0 ...
- 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)
1367: [Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Ou ...
随机推荐
- ambari-server启动WARN qtp-ambari-client-87] ServletHandler: 563 /api/v1/stacks/HDP/versions/2.4/recommendations java.lang.NullPointerException报错解决办法(图文详解)
问题详情 来源是,我在Ambari集群里,安装Hue. 给Ambari集群里安装可视化分析利器工具Hue步骤(图文详解 所遇到的这个问题. 然后,去ambari-server的log日志,查看,如 ...
- AJPFX区分this和super
this和super的区别No.区别thissuper1操作属性this.属性:表示调用本类中的属性,如果本类中的属性不存在,则从父类查找super.属性:表示调用父类中的属性2操作方法this.方法 ...
- 用nowrap实现div内的元素不换行
在编写自定义插件my-slider的过程中,发现无论float还是inline-block均不能保证div内的内容不换行(这两个属性在内容超出容器尺寸后,均将剩余内容做换行处理),在浏览器内比较了自己 ...
- TabLayout+ViewPager实现标签卡效果
转载请注明原文地址:http://www.cnblogs.com/yanyojun/p/8082391.html 代码已经上传至Github:https://github.com/YanYoJun/V ...
- Android基础TOP3:线性布局的特点,常用属性,及权重值
线性布局是一种让视图水平或者垂直布排列的布局: 常用属性: androuid:orientation :表示布局方向 取值vertical表示垂直布局 取值horizontal表示水平布局 andro ...
- VBox虚拟机安装debian
决定在win7上装一个Linux虚拟机用作Linux开发学习,虽然win7下已经有了Cygwin,还是想在一个比较完整的环境下.前面装过Ubuntu发现界面太笨重了,考虑重新换一个,同时比较喜欢apt ...
- Redis缓存Object,List对象
一.到目前为止(jedis-2.2.0.jar),在Jedis中其实并没有提供这样的API对对象,或者是List对象的直接缓存,即并没有如下类似的API jedis.set(String key, O ...
- MySQL性能优化之max_connections配置
MySQL的最大连接数,增加该值增加mysqld 要求的文件描述符的数量.如果服务器的并发连接请求量比较大,建议调高此值,以增加并行连接数量,当然这建立在机器能支撑的情况下,因为如果连接数越多,介于M ...
- C#通过post发送接收数据流
发送数据流方法 /// <summary> /// /// </summary> /// <param name="url">目标url< ...
- 解决android的键盘弹出时,html页面的高度被压缩
如果元素的高度是用100%表示,那么,安卓的键盘弹出时,高度会发生变化,导致布局混乱,所以最好给高度设置像素高度 $("html,body").height(window.inne ...