[luogu4331]数字序列
令$a'_{i}=a_{i}+n-i$、$b'_{i}=b_{i}+n-i$,代价仍然是$\sum_{i=1}^{n}|a'_{i}-b'_{i}|$,但条件变为了$b'_{i}\le b'_{i+1}$,即不下降(以下为了方便,$a'_{i}$和$b'_{i}$仍然用$a_{i}$和$b_{i}$表示,原来的不需要考虑)
考虑暴力dp,令$f_{i,j}$表示前$i$个数且$b_{i}=j$的最小的代价,转移时先令$f_{i-1,j}=\min_{k\le j}f_{i-1,k}$,再加上绝对值,即$f_{i,j}=f_{i-1,j}+|a_{i}-j|$
由于过程是交替进行的,可以看作先加上绝对值再取min(体现在定义上就是$f_{i,j}$表示前$i$个数且$b_{i}\le j$的最小的代价),细节上由于第1次全部都是0本身就不需要取min,然后最后答案即为$f_{n,\infty}$
归纳$f_{i}$具有以下性质:其斜率单调不递增且小于等于0(即下凸但没有上升的部分)
在这一条件下,对于取绝对值再取min的过程,可以看作:对于$a_{i}$左半部分相当于斜率增加1,对于$a_{i}$右半部分斜率减少1,特别的,由于要取min,因此对于斜率为0的部分仍然不变
(做法上有一点类似[AGC049E](https://www.cnblogs.com/PYWBKTDA/p/14015313.html))
定义$f'_{i,j}=f_{i,j}-f_{i,j-1}$($j\ge 1$),特别的$f'_{i,0}=\sum_{j=1}^{i}a_{i}$,那么$f_{i,j}=\sum_{k=0}^{j}f'_{i,k}$(其实后面两点不重要,因为求答案肯定通过构造出来的方案求更方便QAQ)
然后对于$f'_{i,j}$($1\le j\le a_{i}$)区间减1,对于$f'_{i,j}$($a_{i}<j$且$f'_{i,j}<0$)区间加1,直接用线段树维护即可
关于最优解的构造:先有$b_{n}=\min_{f'_{n,k}=0}k$,然后再令$b_{i}=\min(b_{i+1},\min_{f'_{i,k}=0}k-1)$即可(很明显$b_{i+1}$之前$f_{i,j}$最小的位置就是这里,同时这里的$f_{i,j}$不会是跟$f_{i,j-1}$取min的结果)


1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 1000005
4 #define L (k<<1)
5 #define R (L+1)
6 #define mid (l+r>>1)
7 map<int,int>mat;
8 map<int,int>::iterator it;
9 int n,m,a[N],b[N],val[N],f[N<<2],tag[N<<2];
10 long long ans;
11 char ch[21];
12 int read(){
13 int x=0;
14 char c=getchar();
15 while ((c<'0')||(c>'9'))c=getchar();
16 while (('0'<=c)&&(c<='9')){
17 x=x*10+c-'0';
18 c=getchar();
19 }
20 return x;
21 }
22 void write(int k){
23 int s=0;
24 while (k){
25 ch[++s]=k%10+'0';
26 k/=10;
27 }
28 while (s)putchar(ch[s--]);
29 putchar(' ');
30 }
31 void upd(int k,int x){
32 tag[k]+=x;
33 f[k]+=x;
34 }
35 void down(int k){
36 upd(L,tag[k]);
37 upd(R,tag[k]);
38 tag[k]=0;
39 }
40 void update(int k,int l,int r,int x,int y,int z){
41 if ((l>y)||(x>r))return;
42 if ((x<=l)&&(r<=y)){
43 upd(k,z);
44 return;
45 }
46 down(k);
47 update(L,l,mid,x,y,z);
48 update(R,mid+1,r,x,y,z);
49 f[k]=min(f[L],f[R]);
50 }
51 int query(int k,int l,int r){
52 if (l==r)return l;
53 down(k);
54 if (f[R])return query(R,mid+1,r);
55 return query(L,l,mid);
56 }
57 int main(){
58 scanf("%d",&n);
59 for(int i=1;i<=n;i++)a[i]=read()+n-i;
60 memcpy(val,a,sizeof(val));
61 sort(val+1,val+n+1);
62 m=unique(val+1,val+n+1)-val-1;
63 for(int i=1;i<=n;i++)a[i]=lower_bound(val+1,val+m+1,a[i])-val;
64 for(int i=1;i<=n;i++){
65 update(1,1,m,1,a[i],-1);
66 if (i>1)update(1,1,m,a[i]+1,query(1,1,m),1);
67 b[i]=query(1,1,m);
68 }
69 for(int i=n-1;i;i--)b[i]=min(b[i],b[i+1]);
70 for(int i=1;i<=n;i++)ans+=abs(val[a[i]]-val[b[i]]);
71 printf("%lld\n",ans);
72 for(int i=1;i<=n;i++)write(val[b[i]]-n+i);
73 }
[luogu4331]数字序列的更多相关文章
- 找出数组中最长的连续数字序列(JavaScript实现)
原始题目: 给定一个无序的整数序列, 找最长的连续数字序列. 例如: 给定[100, 4, 200, 1, 3, 2], 最长的连续数字序列是[1, 2, 3, 4]. 小菜给出的解法: functi ...
- 九度OJ 1544 数字序列区间最小值
题目地址:http://ac.jobdu.com/problem.php?pid=1544 题目描述: 给定一个数字序列,查询任意给定区间内数字的最小值. 输入: 输入包含多组测试用例,每组测试用例的 ...
- 【BZOJ】【1049】【HAOI2006】数字序列
DP 第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT 题解:http://pan.baidu.com/share/ ...
- kaggle之数字序列预测
数字序列预测 Github地址 Kaggle地址 # -*- coding: UTF-8 -*- %matplotlib inline import pandas as pd import strin ...
- string 数字序列大小比较
string 数字序列大小比较 string.compare string a = "022"; string b="1"; 比较结果 '022' < ' ...
- codevs 2622 数字序列
2622 数字序列 提交地址:http://codevs.cn/problem/2622/ 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 De ...
- Shell生成数字序列
转自http://kodango.com/generate-number-sequence-in-shell Shell里怎么输出指定的数字序列: for i in {1..5}; do echo $ ...
- 《剑指offer》第四十四题(数字序列中某一位的数字)
// 面试题44:数字序列中某一位的数字 // 题目:数字以0123456789101112131415…的格式序列化到一个字符序列中.在这 // 个序列中,第5位(从0开始计数)是5,第13位是1, ...
- 【BZOJ1049】 [HAOI2006]数字序列
BZOJ1049 [HAOI2006]数字序列 dp好题? 第一问 第一问我会做!令\(b_i=a_i-i\),求一个最长不下降子序列. \(n-ans\)就是最终的答案. 第二问 好难啊.不会.挖坑 ...
随机推荐
- 从零入门 Serverless | 教你 7 步快速构建 GitLab 持续集成环境
作者 | 存诚 阿里云弹性计算团队 本文整理自<Serverless 技术公开课>,"Serverless"公众号后台回复"入门",即可获取系列文章 ...
- Java实现红黑树(平衡二叉树)
前言 在实现红黑树之前,我们先来了解一下符号表. 符号表的描述借鉴了Algorithms第四版,详情在:https://algs4.cs.princeton.edu/home/ 符号表有时候被称为字典 ...
- 小白自制Linux开发板 五. Debian文件系统制作,以及WIFI配置、交换分区配置
该片文章将完整记录一个Debian的最小文件系统的生成,以及自定义配置WIFI组件.网络组件和交换分区配置 本文章参考:https://whycan.com/t_4236.htmlhttp://www ...
- Java(35)IO特殊操作流&Properties集合
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228454.html 博客主页:https://www.cnblogs.com/testero ...
- 【Docker】(11)---Docker的网络概念
一.实现原理 1.实现原理 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为C ...
- 【Java虚拟机8】自定义类加载器、类加载器命名空间、类的卸载
前言 学习类加载器就一定要自己实现一个类加载器,今天就从一个简单的自定义类加载器说起. 自定义类加载器 例1 一个简单的类加载器,从一个给定的二进制名字读取一个字节码文件的内容,然后生成对应的clas ...
- Java:创建对象小记
Java:创建对象小记 对 Java 中的创建对象的内容,做一个微不足道的小小小小记 创建对象的方式概述 使用 new 关键字:Person person = new Person(); 反射创建:使 ...
- seata整合多数据源
seata整合多数据源 一.背景 二.整合步骤 1.seata server的搭建 2.引入数据源切换组件 3.引入seata组件 4.配置多数据源 5.关闭seata自己默认的数据源代理 6.配置s ...
- 21.6.29 test
\(NOI\) 模拟赛 \(T1\) 正解是个题解难以理解的数论,结果是组合数相加.暴力分拿满了,尝试打了 \(20*20\) 的表,最后大概打出了个三角形的表,并且帮我找到了一些性质.\(45\)p ...
- 视频编码GOP
GOP group of pictures GOP 指的就是两个I帧之间的间隔. 比较说GOP为120,如果是720 p60 的话,那就是2s一次I帧. 在视频编码序列中,主要有三种编码帧:I帧.P帧 ...