P2501 [HAOI2006]数字序列

题意

P2501 [HAOI2006]数字序列

给定一个\(n\)个数的序列,问最少改变多少个数能让它变成一个单调严格上升的序列,且让每个数改变的绝对值之和最小,输出个数和最小值

\(1\le n\le3.5*10^4,1\le a_i\le 10^5\)

思路

  • \(Problem\ 1\)

题目之后,淦,这什么东西啊

我陷入了满足的数应该被改变的思考中......嗯,想不出来

正着想不出来可以反着想,考虑满足什么条件的数应该被保留

如果\(a[i]\)\(a[j]\)之间的数本身合法或者能被改成合法的那么它们就是应该被保留的

容易得出满足\(a[j]-a[i]\ge j-i\)

\(a[j]-j\ge a[i]-i\)

显然,可以令\(b[i]=a[i]-i\),然后求\(b\)的最大不下降子序列(因为条件是\(\ge\))的长度\(len\)\(n-len\)即为第一问答案

  • \(Problem\ 2\)

我们继续在\(b\)上考虑,对于一对被保留的点\(b[i]\)\(b[j]\),他们之间的数一定都是不合法

现在的问题就在于如何把这些数都改变才能使改变量最小

一个结论

设分界点为\(k\),则对于左边\(b[l] \to b[i],l\in[i,k]\)对于右边\(b[r]\to b[j],r\in [k+1,j]\)

证明的话就不写了,我也不会

\(g[i]\)表示\([1,i]\)的在改变次数最小时最小改变量之和

\(g[i]=\min(g[j]+w(j+1,i))\)

根据上面的结论可以通过前缀和和后缀和来优化求\(w(j+1,i)\)的过程

复杂度为\(O(n^2+nlogn)\),期望得分:\(100\)

/*
@ author:pyyyyyy/guhl37
-----思路------

-----debug-------

*/
#include<bits/stdc++.h>
#include<algorithm>
#define int long long 
using namespace std;
const int N=35005;
const int M=200005;
struct node
{
	int Next,to;
}e[N<<1]; 
int head[N],cnt;
void add(int u,int v)
{
	e[++cnt].Next=head[u];
	head[u]=cnt;
	e[cnt].to=v;
}
int n,a[N],f[N],g[N],pre[N],suf[N];
int st[N],top;
void solve1()
{
	f[0]=0;a[0]=-0x3f3f3f;a[++n]=0x3f3f3f;
	f[1]=1;st[1]=a[1];top=1;
	for(int i=2;i<=n;++i)
	{
		if(st[top]<=a[i]) st[++top]=a[i],f[i]=top;
		else 
		{
			int tmp=upper_bound(st+1,st+1+top,a[i])-st;
			st[tmp]=a[i];f[i]=tmp;
		}
	}
	cout<<n-f[n]<<'\n';
}
void solve2()
{
	memset(g,0x3f3f3f,sizeof(g));g[0]=0;
	for(int i=0;i<=n;++i) add(f[i],i);//注意这里要从f[0]开始建立映射 
	for(int i=1;i<=n;++i)
	{
		for(int j=head[f[i]-1];j;j=e[j].Next)
		{
			int to=e[j].to;
			if(to>i||a[to]>a[i]) continue;
			for(int k=to;k<=i;++k) pre[k]=abs(a[k]-a[to]),suf[k]=abs(a[k]-a[i]);
			for(int k=to;k<=i;++k) pre[k]+=pre[k-1],suf[k]+=suf[k-1];
			for(int k=to;k<i;++k) g[i]=min(g[i],g[to]+pre[k]-pre[to]+suf[i]-suf[k]); 
		}
	}
	cout<<g[n]<<'\n';
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]),a[i]-=i;
	solve1();
	solve2();
	return 0;
}
posted @ 2020-06-17 10:45  pyyyyyy  阅读(369)  评论(0编辑  收藏  举报