题目描述:

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

样例输入

7 9 4 8 20 14 15 18

样例输出

13

提示

所求的Z序列为6,7,8,13,14,15,18.

R=13

题解:

考虑t1>=t2>=t3>=t4这种递减的情况,那么整个z只需取t数组的中位数即可。

由于z是递增数列,不能全取一样的数。所以我们把t[i]-i;保证z数组就可以取一样的数了 且不会影响答案,因为t[i]-i的同时,求出来z[i]也是减了i的

那么我们就采取分治的思想,把原数列分成m个递减区间,然后分别取中位数,使得该区间的差值尽量小.

设X[i]为没个区间的中位数,那么如果X[i]<X[i-1]时不满足z[i]递增的题意,所以要合并,且合并后的答案会更优。(见网上的论文证明)

以下是详细做法和证明:

还有一个我的傻逼错误

ldis()和rdis()没写return 居然函数没有返回值不warning,浪费了很久

代码如下:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=;
typedef long long ll;
ll gi()
{
ll str=;char ch=getchar();
while(ch>'' || ch<'')ch=getchar();
while(ch>='' && ch<='')str=str*+ch-'',ch=getchar();
return str;
}
struct node
{
int dis,size,ls,rs;ll x;
node *l,*r;
int ldis(){return l?l->dis:;}
int rdis(){return r?r->dis:;}
}T[N];
ll a[N];node *root[N],*pos=T;
ll st[N],top=;
ll ans=;
void updata(node *&R)
{
if(R)R->size=(R->l?R->l->size:)+(R->r?R->r->size:)+;
}
node *merge(node *p,node *q)
{
if(!p||!q){return p?p:q;}
if(p->x<q->x)swap(p,q);
if(p->ls>q->ls)p->ls=q->ls;
if(p->rs<q->rs)p->rs=q->rs;
p->r=merge(p->r,q);
if(p->ldis()<p->rdis())swap(p->l,p->r);
p->dis=p->rdis()+;
updata(p);
return p;
}
void Delet(int x)
{
node *y=root[x];
root[x]=merge(root[x]->r,root[x]->l);
root[x]->ls=y->ls;root[x]->rs=y->rs;
y->l=y->r=NULL;y->size=;
}
int main()
{
int n=gi(),k;
for(int i=;i<=n;i++){
a[i]=gi()-i;
pos->l=pos->r=NULL;pos->x=a[i];pos->size=;
pos->ls=pos->rs=i;
root[i]=pos;pos->dis=;
pos++;
}
int now;
st[++top]=;
for(int i=;i<=n;i++){
now=i;
while(top){
k=st[top];
if(root[k]->x>root[now]->x){
top--;
root[k]=merge(root[now],root[k]);
while((root[k]->size<<)>(root[k]->rs-root[k]->ls+))Delet(k);
now=k;
if(!top){
st[++top]=now;
break;
}
}
else{
st[++top]=now;
break;
}
}
}
while(top){
k=st[top];top--;
for(int i=root[k]->ls;i<=root[k]->rs;i++)ans+=abs(root[k]->x-a[i]);
}
cout<<ans;
return ;
}

最新文章

  1. Android中AIDL通信机制分析
  2. BEA-150021 - The admin server failed to authenticate the identity of the user username starting the managed server.
  3. 一步一步开发sniffer(Winpcap+MFC)(一)工欲善其事,必先配环境——配置winpcap开发环境(图文并茂,非常清楚)
  4. FLASK初步实践
  5. c#使用Dictionary统计字符串中出现次数最多字符
  6. MVC超链接
  7. 【bzoj3809】Gty的二逼妹子序列
  8. HTML5详解(一)
  9. SQL 存储过程 多条件 分页查询 性能优化
  10. 【55】java异常机制剖析
  11. Linux 中进程的管理
  12. Django08-批量创建数据
  13. windows下配置 GNU的gdb调试功能
  14. (转第二方案)在 ASP.NET 環境下使用 Memcached 快速上手指南
  15. Ubuntu 登陆界面无限循环问题 以及 root用户无法使用命令问题
  16. 多线程--Java
  17. PHP在win7安装Phalcon框架
  18. ubuntu git 简单入门【转】
  19. 什么是 DDoS 攻击?
  20. [bzoj3132]上帝造题的七分钟——二维树状数组

热门文章

  1. Beta版本展示
  2. APP案例分析
  3. 利用python实现简单随机验证码
  4. 本地通知UILocalNotification
  5. 算法第四版学习笔记之优先队列--Priority Queues
  6. 英语日常词汇:living-room、dining-room vs dining hall
  7. Docker学习笔记 - Docker的数据卷容器
  8. JSON(三)——java中对于JSON格式数据的解析之json-lib与jackson
  9. multiprocessing.Process() ----------python中的多进程
  10. slf4j入门