最终每一个点的值一定为某个ci,将ci离散化。
区间dp,设f[i][j][k]表示当区间 [ i , j ] 中的最小值为k时的最大收益。
转移:f[i][j][k]=max(f[i][x-1][q1]+f[x+1][j][q2]+cnt*k)(q1,q2>=k)
val为左端点在 [i,x] 且右端点在 [x,i] 且值大于等于k的区间个数。
时间复杂度O(n^3*m)。
#include <bits/stdc++.h>
using namespace std;
#define N 52
#define M 4010
#define ll long long
int n,m,cnt,top;
int l[M],r[M],c[M],a[M],pos[N][N][M],val[N][N][M];
ll f[N][N][M],sum[N][N][M],st[M];
void print(int l,int r,int v)
{
if(l>r)return;
int t=val[l][r][v];
print(l,pos[l][r][v]-1,t);
printf("%d ",a[t]);
print(pos[l][r][v]+1,r,t);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&l[i],&r[i],&c[i]),a[i]=c[i];
cnt=m;sort(a+1,a+1+cnt);
cnt=unique(a+1,a+1+cnt)-a-1;
for(int i=0;i<n;i++)
for(int j=1;j+i<=n;j++)
{
for(int k=j;k<=j+i;k++)
{
top=0;
for(int t=1;t<=m;t++)
if(l[t]>=j&&r[t]<=j+i&&l[t]<=k&&r[t]>=k)
st[++top]=c[t];
sort(st+1,st+1+top);
for(int t=1,now=1;t<=cnt;t++)
{
while(now<=top&&st[now]<a[t])now++;
ll t1=sum[j][k-1][t]+sum[k+1][j+i][t]+(ll)a[t]*(top-now+1);
if(t1>=f[j][j+i][t])
{
f[j][j+i][t]=t1;
pos[j][j+i][t]=k;
}
}
}
for(int k=cnt;k>=1;k--)
{
val[j][j+i][k]=k;
if(f[j][j+i][k]<sum[j][j+i][k+1])
{
pos[j][j+i][k]=pos[j][j+i][k+1];
val[j][j+i][k]=val[j][j+i][k+1];
}
sum[j][j+i][k]=max(sum[j][j+i][k+1],f[j][j+i][k]);
}
}
printf("%lld\n",sum[1][n][1]);
print(1,n,1);
return 0;
}
741

被折叠的 条评论
为什么被折叠?



