区间dp 和一些优化(针对P3417)

P3417\(\mathbf{} \begin{Bmatrix} \frac{{\Large LUOGU-P3417} }{{\color{Red}\Large Solution} }\mathbf{} {No.7} \end{Bmatrix}\times{}\) NeeDna

P3146 [USACO16OPEN] 248 G

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+10;
int n,a[N],f[N][N],ans;
signed main(){
	cin>>n;
    for(int i=1;i<=n;i++){cin>>f[i][i];}//输入 
    for(int len=2;len<=n;len++){
    	for(int l=1;l<=n-len+1;l++){//区间大小 l k r 
    		int r=l+len-1;
    		for(int k=l;k<r;k++){
    			if(f[l][k]==f[k+1][r]&&f[l][k]>0){//f[l][k]=f[k+1][r]=0 时 会错误更新!!
    				f[l][r]=max(f[l][r],f[l][k]+1);
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			ans=max(ans,f[i][j]);//最大值不应是f[1][n] 
		}
	}
	cout<<ans;
	return 0;
}

加强版 p3417
思路:区间合并时,应该有相等的两个区间,所以可以用倍增的思想解决这个问题,固然会设计一个关于位置为内容的dp。可以设\(f\left [ i \right ] \left [ j \right ]\) 为左端点为 \(j\) 合并后数字大小为 \(i\) 的右端点值:两个小区间合并可以得到 \(f\left [ i \right ] \left [ j \right ] = f\left [ i-1 \right ] \left [ f\left [ i-1 \right ] \left [ j \right ] \right ]\)。思考复杂度 为 $O\left ( N\times maxNUM\right ) $ maxnum=58 具体求法如下 应为2^18=Nmax,类似2048游戏,两个合成一个,最多会加到40+18=58

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int a[N],f[60][N],n,ans;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
    	cin>>a[i];f[a[i]][i]=i+1;
	}
	for(int i=2;i<=58;i++){
		for(int j=1;j<=n;j++){
			if(!f[i][j]) f[i][j]=f[i-1][f[i-1][j]];
			if(f[i][j])ans=i;
		}
	}
	cout<<ans;
	return 0;
}

posted @ 2025-05-30 20:42  NeeDna  阅读(9)  评论(0)    收藏  举报