首页 > 其他分享 >解题报告P2501 [HAOI2006] 数字序列

解题报告P2501 [HAOI2006] 数字序列

时间:2024-01-13 15:26:58浏览次数:27  
标签:le leq int ll tot P2501 HAOI2006 解题 序列

P2501 [HAOI2006] 数字序列

题目描述

现在我们有一个长度为 \(n\) 的整数序列 \(a\)。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。

输入格式

第一行是一个整数,表示序列长度 \(n\)。
第二行有 \(n\) 个整数,第 \(i\) 个整数表示序列的第 \(i\) 项 \(a_i\)。

输出格式

第一行输出一个整数,表示最少需要改变多少个数。

第二行输出一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。

样例 #1

样例输入 #1
4
5 2 3 5
样例输出 #1
1
4

数据规模与约定

  • 对于 \(90\%\) 的数据,保证 \(n \leq 6 \times 10^3\)。
  • 对于 \(100\%\) 的数据,保证 \(1 \leq n \leq 3.5 \times 10^4\),\(1 \leq a_i \leq 10^5\)。数据保证 \(a_i\) 随机生成。

解析

先看第一问。

我们考虑什么样的数需要保留。首先选定一个数 \(a_i\) 作为基准,考虑在它后面的某个数 \(a_j\),那么只有当 \(a_j-a_i\ge i-j\) 时才有可能保留。那么我们构建一个新的数列 \(b_i=a_i-i\) ,它的最长不下降子序列元素个数就是我们最多保留的数。

对于第二问,首先我们可以知道,原问题等价于把 \(b\) 数组改得单调不降。

我们首先考虑 \(b\) 的最长上升子序列中的两个相邻元素 \(b_j,b_i(j\le i)\)。

修改前 \(b_i\) 和 \(b_j\) 之间的数字一定 \(\not\in [b_j,b_i]\),而合法的序列一定在 \([b_j,b_i]\) 内。首先我们可以想到把在外面的数全部移到最近的边界上,最优解一定是在这个基础上构造出来的。

然后我们考虑怎样继续构造是最优的。实际上,最优的解的形态肯定是以一个 \(k\in[j,i]\) 为分界点,\(b_{x\le k}=b_j,\ b_{x>k}=b_i\) 的一个情况。

为什么呢?我们先假设有一部分连续子序列夹在中间

对于只有一个元素的情况是显然的,把它移到靠近初始位置的那个 \(b\) 更优秀。

对于多个元素,我们考虑对于这个子段向两边移动的代价。《容易发现》我们总是可以无偿甚至减少代价地将其转移到某种上文所述的最优解的情况。

于是我们设 \(h(i)\) 为 \([1,i]\) 区间内的修改代价最小值。那么转移方程如下:

\[h(i)=\underset{f(i)=f(j)+1}{\min}\{\ h(j)+w(j+1,i-1)\} \]

其中

\[w(l,r)=\underset{l\le k\le r}{\min}\{\sum_{i=l}^k|b_i-b_l|+\sum_{i=k+1}^r|b_i-b_r|\} \]

一些实现上的小细节

可以在做第一问的时候就用 vector 预处理出状态转移:即存一下所有长度为 \(i\) 的子序列末尾。

由于 LCS 的前后可能还有元素要处理,所以添加 \(b_0=-\infty,b_{n+1}=+\infty\)。

记得开 long long 以及枚举间断点 \(k\) 的时候只能枚举到 \(i-1\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=4e4+10;
const ll inf=0x3f3f3f3f;

int n;
ll a[N],b[N],h[N];
int g[N],f[N];
vector<int> vec[N];

ll pre[N],suf[N];
void init(int l,int r)
{
	if(l>r) return ;
	pre[l]=0,suf[r-1]=0;
	for(int i=l+1;i<=r-1;i++) pre[i]=pre[i-1]+abs(b[i]-b[l]);
	for(int i=r-1;i>=l;i--) suf[i]=suf[i+1]+abs(b[i+1]-b[r]);

}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++) b[i]=a[i]-(ll)i;
	int tot=1;
	g[tot]=b[1];f[1]=1;vec[1].push_back(1); b[n+1]=inf;
	for(int i=2;i<=n+1;i++)//最长不下降
	{
		if(b[i]>=g[tot])
		{
			g[++tot]=b[i];
			vec[tot].push_back(i);
			f[i]=tot;
		}
		else
		{
			int l=upper_bound(g+1,g+1+tot,b[i])-g;
			g[l]=b[i]; vec[l].push_back(i);
			f[i]=l;
		}
	}
	printf("%d\n",n-tot+1);
	b[0]=-inf;
	memset(h,0x3f3f3f3f,sizeof h);
	h[0]=0; vec[0].push_back(0);
	for(int i=1;i<=n+1;i++)
	{
		for(int p=0;p<vec[f[i]-1].size();p++)
		{
			int j=vec[f[i]-1][p];
			if(j>i||b[j]>b[i]) continue;
			init(j,i);
			for(int k=j;k<i;k++)
			{
				h[i]=min(h[i],h[j]+pre[k]+suf[k]);
			}
		}
	}
	printf("%lld",h[n+1]);
	return 0;
}

标签:le,leq,int,ll,tot,P2501,HAOI2006,解题,序列
From: https://www.cnblogs.com/IzayoiMiku/p/17962372

相关文章

  • 二叉树解题思路小记
    二叉树前中后序位置代码框架voidtraverse(TreeNoderoot){if(root==null){return;}//前序位置traverse(root.left);//中序位置traverse(root.right);//后序位置}代码写在不同的位置,只是执行的时间不同。前序位置刚刚进入二......
  • BJOI 2017 解题报告
    P3713机动训练关键在于trick:\(\suma_i^2\)可以视为两个人走了相同的路径的方案数,证明是容易的:对不同的机动路径求相同的方案数,每种个数为\(a_i\)的机动路径会产生\(a_i^2\)种本质相同的走法。如果令\(dp[x][y][a][b]\)为两个人分别走到\((x,y)\)和\((a,b)\)的本......
  • BJOI 2018 解题报告
    P4427[BJOI2018]求和谔谔题。这个问题看上去很不可维护,而且让我想到了P5305旧词。结果发现怎么\(k\le50\),那我直接跑\(50\)遍不就好了?P4429[BJOI2018]染色神仙题。考虑先用一些比较简单的情况搞到一些性质继续研究。那我们不妨只对原图黑白染色,得到性质“原图必为二分......
  • BJOI 2019 解题报告
    P5319[BJOI2019]奥术神杖数学题。搞掉几何平均数的方法是左右取对数,然后变成一个经典的\(0/1\)分数规划问题。解决方法是二分答案后AC自动机+DP。P5322[BJOI2019]排兵布阵简单题。随便DP即可,五分钟之内没想出这道题的赶快去加训。P5320[BJOI2019]勘破神机科技......
  • 三道初三数学模拟几何综合题的解题思路解析
     ......
  • 【WinDbg】学习以及在CTF中解题
    1、WinDbg介绍WinDbg是一款Windows强大的调试器,可以调试0和3环的程序。在实际开发中,可以调试我们的错误程序,从而定位关键代码,进行程序代码修复。WinDbg是一种调试器工具,由微软公司开发,用于分析和调试Windows操作系统和应用程序。它提供了强大的调试功能,可以帮助开发人员识别......
  • 【代码注释即解题思路】1796. 字符串中第二大的数字
    一、题目描述给你一个混合字符串s,请你返回s中第二大的数字,如果不存在第二大的数字,请你返回-1。混合字符串由小写英文字母和数字组成。示例1:输入:s="dfa12321afd"输出:2解释:出现在s中的数字包括[1,2,3]。第二大的数字是2。示例2:输入:s="abc1111"输出:-1解释:......
  • STM32在CTF中的应用和快速解题
    题目给的是bin文件,基本上就是需要我们手动修复的固件逆向。如果给的是hex文件,我们可能需要使用MKD进行动态调试主要还是以做题为目的详细的可以去看文档:https://pdf1.alldatasheet.com/datasheet-pdf/view/201596/STMICROELECTRONICS/STM32F103C8T6.htmlSVD文件下载:https://gi......
  • 2023.12.12 校赛解题报告
    7-1点菜题面Congruent和ComistryMo两个人正在饭店吃饭,饭店里面一共有\(n\)道菜,每道菜有一个价格\(a_i\)​\((1≤i≤n)\)。他俩会在饭店按顺序点\(k\)道菜(可以不连续,保证相对顺序即可),假设点的菜序列为\(S_1−S_k\)。他们约定:一个人付所有奇数下标已点菜品价格的最大......
  • 全局平衡二叉树学习笔记 && [SDOI2017]切树游戏解题报告
    首先,任何一个卡树剖的出题人都很没有素质前言2023年8月22日,XDFnoip模拟赛场上,神犇liuhangxin自己发明了矩阵乘法维护FWT,可是出成绩的时候发现本题挂了30分。2023年9月22日,菜鸡cool_milo看到了liuhangxin的题解,但是由于太菜,并没有看懂。2023年10月22日,菜......