bzoj 4380 dp

最终每一个点的值一定为某个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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值