【BZOJ 1049】 [HAOI2006]数字序列

1049: [HAOI2006]数字序列

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 979  Solved: 389

[Submit][Status]

Description

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

Input

第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。

Output

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

Sample Input

4

5 2 3 5

Sample Output

1

4

HINT

【数据范围】

90%的数据n<=6000。

100%的数据n<=35000。

保证所有数列是随机的。

神奇的dp。

对于第一问:

改变的数最少即让不变的数最多,那么类似于求最长上升子序列,只是要求增加:f[i]=max(f[j]+1)  (a[i]-a[j]>=i-j)

把a[i]-a[j]>=i-j移项:

a[i]-i>=a[j]-j

因此把每一个数都减去i,直接求LIS即可(用nlogn的算法)

对于第二问(注意:此时每个数已经减去i了!!):

我们要求使得a数组单调不减的最少改变量。

ydc题解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define M 35005
#define LL long long
using namespace std;
LL g[M],s1[M],s2[M];
struct edge
{
	int y,ne;
}e[M];
int m[M],cnt,h[M],a[M],n,f[M];
void read(int &tmp)
{
	tmp=0;
	char ch=getchar();
	int fu=1;
	for (;ch<'0'||ch>'9';ch=getchar())
		if (ch=='-') fu=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())
		tmp=tmp*10+ch-'0';
	tmp*=fu;
}
void Solve1()
{
	memset(m,127,sizeof(m));
	int ma=1;
	m[1]=a[1],f[1]=1;
	for (int i=2;i<=n;i++)
	{
		int l=1,r=ma,ans=0;
		while (l<=r)
		{
			int mid=(l+r)>>1;
			if (m[mid]<=a[i]) ans=mid,l=mid+1;
			else r=mid-1;
		}
		f[i]=ans+1;
		ma=max(ma,f[i]);
		m[f[i]]=min(m[f[i]],a[i]);
	}
	printf("%d\n",n-f[n]);
}
void Insert(int x,int y)
{
	e[++cnt].y=y;
	e[cnt].ne=h[x];
	h[x]=cnt;
}
void Solve2()
{
	for (int i=n;i>=0;i--)
	{
		Insert(f[i],i);
		g[i]=1LL<<60;
	}
	g[0]=0,a[0]=-1<<30;
	for (int i=1;i<=n;i++)
		for (int j=h[f[i]-1];j;j=e[j].ne)
		{
			int p=e[j].y;
			if (p>i) break;
			if (a[p]>a[i]) continue;
			for (int k=p;k<=i;k++)
				s1[k]=abs(a[p]-a[k]),s2[k]=abs(a[i]-a[k]);
			for (int k=p+1;k<=i;k++)
				s1[k]+=s1[k-1],s2[k]+=s2[k-1];
			for (int k=p;k<i;k++)
				g[i]=min(g[i],g[p]+s1[k]-s1[p]+s2[i]-s2[k]);
		}
	cout<<g[n]<<endl;
}
int main()
{
        read(n);
	for (int i=1;i<=n;i++)
		read(a[i]),a[i]-=i;
	a[++n]=1<<30;
	Solve1();
	Solve2();
	return 0;
}

感悟:

1.WA无数次:第一问求错,求整个序列的最长不下降序列,我直接把f[n]当做答案了,应该再加一句a[++n]=inf,f[n]才是答案

2.第二问是贪心,发现贪心似乎都是用反证法来证明的。。

时间: 2024-10-17 03:22:42

【BZOJ 1049】 [HAOI2006]数字序列的相关文章

【BZOJ】1049: [HAOI2006]数字序列(lis+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=1049 又是一题神题啊.orz 首先第一个问很容易看出 f[i]=min{f[j]+1, a[i]-a[j]>=i-j} 设b[i]=a[i]-i 得 f[i]=min{f[j]+1, b[i]>=b[j]} 然后就是lis的log算法.... 第二个问,好神!!! 首先发现,如果有b[i]>=b[j]且f[i]==f[j]+1时,区间[j, i]中的点一定都是大于b[i]或者小于b[j],

BZOJ1049: [HAOI2006]数字序列

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1049 题解: ydc的题解:http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411 第二问比较神?考场上敢去猜结论? 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring&g

BZOJ1049 [HAOI2006]数字序列0

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值.n<=35000

[HAOI2006]数字序列

题目描述 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. 输入输出格式 输入格式: 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. 输出格式: 第一行一个整数表示最少需要改变多少个数. 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值. 输入输出样例 输入样例#1: 复制 4 5 2 3 5 输出样例#1: 复制 1 4 说明 [数据范围] 90%的数据n<=

[luogu2501 HAOI2006] 数字序列 (递推LIS)

题目描述 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. 输入输出格式 输入格式: 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. 输出格式: 第一行一个整数表示最少需要改变多少个数. 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值. 输入输出样例 输入样例#1: 4 5 2 3 5 输出样例#1: 1 4 说明 [数据范围] 90%的数据n<=6000.

[HAOI2006] 数字序列 - dp,二分

现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大.求在改变的数最少的情况下,每个数改变的绝对值之和的最小值. \(n\leq 35000\),保证数据随机 Solution 第一问很容易,只需要令 \(b_i=a_i-i\),然后跑最长不下降子序列即可 下面考虑第二问,令 \(f[i]\) 表示前 \(i\) 个数构成的数列要变成单调上升需要改动的最小幅度 若 \(a_i,a_j, i<j\) 满足

p2501 [HAOI2006]数字序列

传送门 分析 https://www.luogu.org/blog/FlierKing/solution-p2501 对于第二问的感性理解就是有上下两条线,一些点在上面的线的上面或者下面的线的下面,然后看它们变成哪个线的位置更优 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<ccty

【BZOJ】【1049】【HAOI2006】数字序列

DP 第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT 题解:http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411 没有将a[0]置为-INF在BZOJ上WA了……so sad…… 1 /************************************************************** 2 Problem: 10

【bzoj1049】【HAOI2006】【数字序列】

1049: [HAOI2006]数字序列 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1117 Solved: 454 [Submit][Status][Discuss] Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. Output 第一行一个整数表示