ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

区间dp(刷表法转移):P5336

2026/8/4 18:55:14 拓冰建站 浏览量
区间dp(刷表法转移):P5336

https://www.luogu.com.cn/problem/P5336

离散化后枚举 g ( l , r , m n , m x ) g(l,r,mn,mx) g(l,r,mn,mx),和 f ( l , r ) f(l,r) f(l,r)(全删情况),然后考虑使用刷表法来转移。

  1. a r + 1 a_{r+1} ar+1 加进来,更新 m n , m x mn,mx mn,mx 即可
  2. 不加进来,停表,干脆枚举分界点来转移(因为要从小加到大)。
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#else#define debug(...) void(0)
#endif
//#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
//#define mo
#define N 55
void Mn(int &a, int b) { a=min(a, b); }
int n, m, i, j, k, T;
int f[N][N], g[N][N][N][N], l, r, len, A, B;
int a[N], b[N]; signed main()
{#ifdef LOCALfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);#endif
//	srand(time(NULL));
//	T=read();
//	while(T--) {
//
//	}n=read(); A=read(); B=read();  for(i=1; i<=n; ++i) a[i]=b[i]=read(); sort(b+1, b+n+1); for(i=1; i<=n; ++i) a[i]=lower_bound(b+1, b+n+1, a[i])-b; memset(g, 0x3f, sizeof(g)); memset(f, 0x3f, sizeof(f)); for(i=1; i<=n; ++i) g[i][i][a[i]][a[i]]=0; for(len=1; len<=n; ++len)for(l=1, r=len; r<=n; ++l, ++r) for(i=1; i<=n; ++i) for(j=i; j<=n; ++j) {for(k=l; k<r; ++k) Mn(g[l][r][i][j], g[l][k][i][j]+f[k+1][r]); Mn(f[l][r], g[l][r][i][j]+A+B*Z(b[j]-b[i])); if(r<n) Mn(g[l][r+1][min(i, a[r+1])][max(j, a[r+1])], g[l][r][i][j]); }printf("%lld\n", f[1][n]); return 0;
}