BZOJ 3594: [Scoi2014]方伯伯的玉米田 【DP优化】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88880346

题目传送门

题目分析:

如果我们用f[i][j]表示前i个数用了j次操作得到的以i为右端点的最长不下降序列长度,枚举前面的决策点转移。
你会发现没办法转移,因为你不知道决策点和i的大小关系。
于是神奇的事情发生了。
你会发现,一次操作的区间一定是形如 [ i , n ] [i,n] 的!
如果你拔高了区间 [ i , j ] [i,j] ,那么显然拔高 [ i , n ] [i,n] 不会更劣。
那么对于p<=i,对p的k次操作,对i同样有效。
那么就可以转移了!
f [ i ] [ j ] = m a x ( f [ p ] [ k ] ) + 1 f[i][j]=max(f[p][k])+1 ,其中 a [ p ] + k a [ i ] + j ,   k j a[p]+k\le a[i]+j,~k\le j
二维树状数组优化一下,就是 O ( n k l o g ( n + k ) l o g k ) O(nklog(n+k)logk) 的复杂度。

Code:

#include<cstdio>
#include<vector>
#include<cctype>
#include<cstring>
#include<algorithm>
#define maxn 10005
using namespace std;
char cb[1<<15],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
	char c;bool f=0;while(!isdigit(c=getc())) if(c=='-') f=1;
	for(a=c-'0';isdigit(c=getc());a=a*10+c-'0'); if(f) a=-a;
}
int n,m,mx,ans,tmp,a[maxn];
int arr[5505][505];
void upd(int x,int y,int d){
	for(int i=x;i<=mx+m;i+=i&-i) for(int j=y;j<=m;j+=j&-j) arr[i][j]=max(arr[i][j],d);
}
int qmax(int x,int y){
	int s=0;
	for(int i=x;i;i-=i&-i) for(int j=y;j;j-=j&-j) s=max(s,arr[i][j]);
	return s;
}
int main()
{
	read(n),read(m),m++;//因为树状数组不能存0,所以整体向后移一位
	for(int i=1;i<=n;i++) read(a[i]),mx=max(mx,a[i]);
	for(int i=1;i<=n;i++)
		for(int j=m;j>=1;j--){
			ans=max(ans,tmp=qmax(a[i]+j,j)+1);
			upd(a[i]+j,j,tmp);
		}
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/88880346
今日推荐