单调队列优化DP——习题收集

前言

感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新。主要做一个收集整理总结工作。

记录

0x01

POJ - 1821 Fence,比较适合入门的题,写出转移方程后可以比较容易的看出决策变量的取值范围的界是单调变化的,以及价值容易写成多项式的形式,单调性易维护。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<"\n"
#define sz(x) int(x.size())
#define All(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
const int maxn=2e4+10,mod=1e9+7,INF=0x3f3f3f3f;
struct node
{
    int l,p,s;
}a[maxn];
bool cmp(node x,node y)
{
    return x.s<y.s;
}
int q[maxn],h,t;
ll f[105][maxn];
inline ll val(int i,int k)
{
    return f[i-1][k]-k*a[i].p;
}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for (int i=1;i<=k;++i)
        scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
    sort(a+1,a+k+1,cmp);
    for (int i=1;i<=k;++i)
    {
        h=0,t=-1;
        for (int k=max(0,a[i].s-a[i].l);k<a[i].s;++k)
        {
            while (h<=t&&val(i,k)>=val(i,q[t]))
                --t;
            q[++t]=k;
        }
        for (int j=1;j<=n;++j)
        {
            f[i][j]=max(f[i-1][j],f[i][j-1]);
            if (j<a[i].s)
                continue;
            while (h<=t&&q[h]<j-a[i].l)
                ++h;
            if (h<=t)
                f[i][j]=max(f[i][j],val(i,q[h])+j*a[i].p);
        }
    }
    cout<<f[k][n];
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/orangee/p/10693748.html