P2501 [HAOI2006]数字序列(LIS&贪心)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2501 [HAOI2006]数字序列(LIS&贪心)相关的知识,希望对你有一定的参考价值。

P2501 [HAOI2006]数字序列(LIS&贪心)

对于一个区间 [ l , r ] [l,r] [l,r],显然需要满足 a r − a l ≥ r − l a_r-a_l\\ge r-l aralrl 才有可能严格递增。

移项: a r − r ≥ a l − l a_r-r\\ge a_l-l arrall

b i = a i − i b_i=a_i-i bi=aii,在数组 b b b中到最长非递减子序列长度 c n t cnt cnt n − c n t n-cnt ncnt就是最少修改的数。

第二问,有一个结论,对于 L I S LIS LIS中相邻的两点,肯定有个分界点 k k k [ l , k ] [l,k] [l,k]修改成 a l a_l al [ k + 1 , r ] [k+1,r] [k+1,r]修改成 a r a_r ar 是最优的。

所以可以预处理修改成 a l , a r a_l,a_r al,ar的前缀和。

然后扫一遍取最值。

为了方便找到子序列中的前一个,我们给每个 f i , i f_i,i fi,i建边 e d g e ( f i , i ) edge(f_i,i) edge(fi,i)

这样每次要找到 f i − 1 f_{i}-1 fi1的位置,就可以直接访问 u = f i − 1 u=f_i-1 u=fi1所连的边。

时间复杂度: O ( n 2 + n l o g n ) O(n^2+nlogn) O(n2+nlogn)

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int maxn=35010;
int n,cnt;
int head[maxn],a[maxn],b[maxn],f[maxn],g[maxn],sum1[maxn],sum2[maxn];
struct edge
{
	int to,nxt;
}e[maxn];
inline void add(int u,int v)
{
	e[++cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].to=v;
}
signed main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]-=i;
	a[++n]=0x3f3f3f3f;a[0]=-0x3f3f3f3f;
	memset(b,0x3f,sizeof(b));b[0]=-0x3f3f3f3f,b[1]=a[1];
	int len=1;
	f[1]=1; 
	for(int i=2;i<=n;i++)
	{
		int tmp=upper_bound(b,b+len+1,a[i])-b;
		len=max(len,tmp);
		f[i]=tmp;
		b[tmp]=a[i];
	}
	printf("%lld\\n",n-len);
	for(int i=0;i<=n;i++)add(f[i],i);
	memset(g,0x3f,sizeof(g));g[0]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=head[f[i]-1];j;j=e[j].nxt)
		{
			int y=e[j].to;
			if(y>i||a[y]>a[i])continue;
			for(int k=y;k<=i;k++)sum1[k]=abs(a[k]-a[y]),sum2[k]=abs(a[k]-a[i]);
			for(int k=y+1;k<=i;k++)sum1[k]+=sum1[k-1],sum2[k]+=sum2[k-1];
			for(int k=y;k<=i-1;k++)g[i]=min(g[i],g[y]+sum1[k]-sum1[y]+sum2[i]-sum2[k]);
		}
	}
	printf("%lld",g[n]);
	return 0;
} 

以上是关于P2501 [HAOI2006]数字序列(LIS&贪心)的主要内容,如果未能解决你的问题,请参考以下文章

P2501 [HAOI2006]数字序列

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

BZOJ 1049: [HAOI2006]数字序列

bzoj1049: [HAOI2006]数字序列

[HAOI2006]数字序列

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